NEM 2009-07-31: Here's a simple interactive tclsh-style application, with the difference that it runs inside a coroutine. This allows you to have complex event-driven interactions appear as if they are happening in a blocking, non-event-driven manner. For example, you can have Tk GUI applications responding to events while you are apparently in a blocking HTTP request.
# corotcl -- # # A coroutine-enabled tclsh # package require Tk proc lambda {params body args} { list ::apply [list $params $body] {*}$args } proc prompt p { puts -nonewline "$p " flush stdout fileevent stdin readable [lambda return { $return [gets stdin] } [info coroutine]] yield } proc get-command {} { set cmd [prompt %] while {![info complete $cmd]} { append cmd \n [prompt >] } return $cmd } proc repl {} { while 1 { set cmd [get-command] set code [catch { uplevel #0 $cmd } result opts] if {$code == 1} { puts [dict get $opts -errorinfo] } else { puts $result } } } coroutine main repl #vwait forever ;# if no Tk
An example of use. First, we bring up a simple Tk interface to check that everything keeps running in the background:
% pack [button .b -text Test -command {puts Test}] .b
Testing this will show that it does print "Test" in the console when clicked. So far, so normal. Now, we create a coroutine-enabled version of http::geturl:
% package require http 2.7.2 % proc fetch url { > http::geturl $url -command [info coroutine] > yield > }
We can now use this to fetch data from the web, just like the usual geturl. The difference is that this works in the background: you can still click on the Tk button and it will still print to the console even while the fetch is still in progress:
% set t [fetch http://wiki.tcl.tk/4] Test Test Test ::http::1
There we go: an interactive Tcl interpreter that is fully coroutine enabled.
Next step? Futures?