[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

#### 2.7.16.3 Interaction combinator

A further combinator allows virtual code applications to interact directly with any interactive console application using the `expect` library. The mechanism is similar to that of interactive applications documented in the Output From Interactive Applications, but attempts to be more convenient. Instead of being designed as an interactive application, any virtual code application may use this combinator to spawn a shell and interact with it in order to compute some desired result.

The advantage of this combinator over the `library` combinator is that it requires no modification of the virtual machine to support new applications. It can also interact with applications that may reside on remote servers, that are implemented languages other than C, or whose source code is unavailable. For example, the GNU R statistical package provides an interactive command to evaluate multivariate normal distribution functions with an arbitrary covariance matrix, but the corresponding function is not provided by the `Rmath` C library (or any other free library, to the author’s knowledge) because it is implemented in interpreted code. This combinator makes it callable by an `avram` virtual code application nevertheless. The disadvantage compared to the `library` combinator is that there is more overhead in spawning a process than simply making a call to a built in function, and the programming interface is more complicated.

The combinator takes the form

T35

  [[`interact`]] f = `((nil,nil),(((nil,nil),nil),((nil,f),nil)))`

where f is the virtual code for a function that follows the same protocol described in Output From Interactive Applications, except that it does not allow file output as described in Mixed Modes of Interaction. The argument `x` is ignored when the expression `(interact f) x` is evaluated, similarly to the way the argument is ignored in an expression like `(constant k) x`. The result returned is a transcript of the dialogue that took place between `f` and the externally spawned shell, represented as a list of lists of strings for line oriented interaction, or a list of characters alternating with lists of strings in the case of character oriented interaction.

The following example demonstrates a trivial use of the `interact` combinator to spawn an `ftp` client, do an `ls` command, and then terminate the session.

    eof = <(nil,(nil,(((nil,nil),nil),(nil,nil))))>

    demo =

    interact conditional(
       conditional(identity,constant false,constant true),
       constant(0,<'ftp'>,<'ftp> '>),
       conditional(
          conditional(left,constant false,constant true),
          constant(1,<'ls',''>,<'','ftp> '>),
          conditional(
             compose(compare,couple(left,constant 1)),
             constant(2,<'bye',''>,<eof>),
             constant nil)))

Some liberties are taken with `silly` syntax in this example, in the way of using angle brackets to denote lists, and numbers to represent states.

- The interacting transducer works by checking whether its argument is empty (via the `identity` function used as a predicate in the `conditional`, which is then negated). In that case it returns the triple containing the initial state of 0, the `ftp` shell command to spawn the client, and the `'ftp> '` prompt expected when the client has been spawned, both of the latter being lists of strings.
- If the argument is non-empty, then next it checks whether it is in the initial state of 0, (via the `left` function used as a predicate, referring to the state variable expected on the left of any given `(state,input)` pair, also negated). If so, it returns the triple containing the next state of 1, the `ls` command followed by an empty string to indicate a line break, and the expected prompt preceded by an empty string to match it only at the beginning of a line.
- Finally, it checks for state 1, in which case it issues the `bye` command to close the session, `eof` rather than a prompt to wait for termination of the client, and a state of 2.
- In the remaining state of 2, which needn’t be explicitly tested because it is the only remaining possibility, the program returns a `nil` value to indicate that the computation has terminated.

Deadlock would be possible at any point if either party did not follow this protocol, but for this example it is not an issue. If an expression of the form `demo x` were to be evaluated, then regardless of the value of `x`, the value of the result would be as shown below.

    <
       <'ftp'>,
       <'ftp> '>,
       <'ls',''>,
       <'ls','Not connected.','ftp> '>,
       <'bye',''>,
       <'bye',''>>

That is, it would be a list of lists of strings, alternating between the output of the interactor and the output of the `ftp` client. If the spawned application had been something non-trivial such as a computer algebra system or a command line web search utility, then it is easy to see how functions using this combinator can leverage off a wealth of available resources.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

This document was generated on November 8, 2012 using texi2html 1.82.