[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]? <>Event Loop