'''[event-oriented programming%|%Asynchronous] [Script] [eval%|%Evaluation] via [coroutine%|%Coroutines] and [chan%|%Channels]''' is a working example of putting the pieces together to harness an interpreter over a channel. ** Description ** [PYK] 2016-04-06: Given a [chan%|%channel] with a Tcl interpreter connected to the other side, what would be the minimal scaffolding necessary to effectively use that interpreter as an asynchronous `[eval]` mechanism? Conceptually it's a simple enough task, but there were enough details to attend to that it took some time to get right. The little system below is small enough to serve as a working example of event-driven [coroutine%|%coroutines] and channels, and is also an example of the "wire protocol" described in [Tool Protocol Language]: A sequence of [list%|%lists] separated by newlines. This is a slight twist the format of a standard Tcl script, but it's perfect for the task of moving arbitray data through a channel, and a worthy alternative to [netstrings]. Wrapping each message as a list containing one item makes it possible for the receiver to use `[info complete]` to separate out the messages. Null characters in the data pose no problem. The first item in each list is the message; additional items might be used to transport out-of-band data or for control streams. There are several other examples of a similar nature, but this one is more of a building block, not tied to [socket%|%sockets] like [comm] is, focused on doing just one thing right. I anticipate using this system to build out a minimal [Distributed computation%|%distributed computing system]. To stay out of the way, the system creates no commands or variables in the remote interpreter. ** Synopsis ** : `init` ''`chan receiver`'' : `send` ''`chan message`'' ** Usage ** '''`init`''' takes a read/write channel connected on the other end to an interpreter. This could be an interpreter in the same thread, in another thread, in another process, or on a remote host; `init` doesn't know and doesn't care, and neither does the rest of the system. The second argument to `init` is a script to send to the other interpreter to install the receiver on that end. '''`receive`''' generates this script. By default, it configures the other interpreter to evaluate scripts that it receives and returns the results. The default command evaluator, to which the incoming script is appended, is: ====== namespace eval :: $command ====== To change this, use the `process` argument. For example, to simply echo the received script: ====== init $writechan $readchan [accept process list] ====== Or to provide a little more detail in the echo: ====== init $writechan $readchan [accept process {list timestamp [clock seconds] script}] ====== '''`send`''' arranges for a message to be sent over the channel, [yield%|%yields], and returns the result of the remote evaluation. ** Demos ** [http://chiselapp.com/user/pooryorick/repository/ycl/artifact?filename=packages/coro/demo/interps&ci=trunk%|%interps]: Demonstrates the use of `[ycl%|%ycl chan interp]` in conjunction with `[ycl coro relay]`. ** Implementation ** See [ycl%|%ycl chan interp]. <> remote interpreter | chan | coroutine