'''[PYK] 2017-08-23''' The '''inter-[coroutine] return''' protocol allows participating [coroutine%|%coroutines] to act as a virtual call stack where one coroutine "returns" to another coroutine by treating that coroutine as if actually was `[return]`. *** See Also *** [ycl%|%ycl coro call]: Based on this protocol, provides workflow helpers for the caller: `call`, `foward`. Workflow helpers for the callee are `hi`, `reply`, `last` and `bye`. Administrative helpers are `autocall` and `body`. ** Description ** In a normal [level%|%call stack], a callee is tightly bound to its caller. When it returns, control returns to the caller. With coroutines this relationship can become more dynamic. A called coroutine can "return" to its "caller", but it could also "return" to some other "caller". In this way, the "call stack" can be composed dynamically. Each participating coroutine uses some coordinated mechanism to decide whether to "return" to its caller or to some other coroutine. In this way this logical "call stack" becomes more like a production line, where output can be rerouted at any moment according to the decisions of some controller. Because standard `[return]` information is being passed around, the Tcl interpreter can handle errors and other return codes in the normal manner. Condition handlers can be dropped into the workflow at any point, and can even "restart" some routine, passing it adjusted data. ** Mechanism ** The calling coroutine does this: ====== set result [return -level 0 {*}[yieldto some other command some arguments [info coroutine]]] ====== Or to process the return options in some custom fashion: ====== catch {return -level 0 {*}[yieldto some other command some arguments [info coroutine]]} cres copts process $copts and behave accordingly ... ====== The returning coroutine treats the the other coroutine as if it was actually `[return]`: ====== set args [yieldto the calling coroutine ${some result} set caller [lindex $args end] set args [lrange $args 0 end-1] ====== Any of the standard arguments to `[return]` can be used: ====== set args [yieldto the calling coroutine -code break] ====== This allows coroutines to interact in an intuitive and customary way. For example, a coroutine might iteratively call another coroutine which returns a series of results and then returns a '''break''' code: ====== while 1 { lappend res [call some other coroutine] } puts $res ====== For its part, '''`some other coroutine`''' would do something like this: ====== while {something is true} { reply ${another value} } yieldto the client -code break ====== In the last two examples, `call` and `reply` are helper commands that eliminate the need to type out the verbose patterns introduced above. In order to do its job, `reply` stores the name of the caller in the coroutine's top level. These and other helpful commands are available in [ycl%|%ycl coro call]. <> coroutine