'''`[http://www.tcl.tk/man/tcl/TclCmd/coroutine.htm%|%yield]`''', a [Tcl Commands%|%built-in] Tcl [command], exits the current coroutine without destroying it, returning a value in the process. ** Synopsis ** : '''yield''' ?''value''? **See Also** [yieldto]: instead of yielding a value directly, execute a command in place of the current coroutine context, which then returns a value. [tcl::unsupported]::[yieldm]: an experiment in passing multiple values to a coroutine. `yieldm` turned out to be trivial to implement in terms of `[yieldto]`. ** Description ** '''`yield`''' arranges for the associated coroutine command of the current coroutine to return ''value'' if it is provided, or the [empty string] otherwise. The current coroutine context continues to exist. The next time the associated coroutine context command is executed, any argument passed to it becomes the return value of the `yield` that previously exited the coroutine context. If the associated coroutine context command is not given an argument, the return value of `yield` is the [empty string]. [DKF]: Can also be thought of as a magical form of [return]. That itself returns (possibly). ** Example: Basic ** ====== proc onetwo {} { yield [info coroutine] yield 1 return 2 } ====== ====== % coroutine count onetwo ::count % count 1 % count 2 % count invalid command name "count" ====== ** Coloop ** [DKF]: If you're trying to build a coroutine that iteratively yields values, it can be a little bit tricky to work out how to string the value passing through '''`yield`''' nicely; the values just don't seem to pass around in a way that feels natural (well, to me anyway). Here's a helper procedure that makes it all much easier: ====== proc coloop {var body} { set val [info coroutine] upvar 1 $var v while 1 { set v [yield $val] set val [uplevel 1 $body] } } ====== With this, you get an automatic yield of the name of the coroutine to start with, and then you can pass values in and have results passed back. The given ''var''iable is set to the value passed in, and the result of evaluating the ''body'' is the next value yielded. You might use it like this: ====== proc summerBody n { coloop x { incr n $x } } coroutine s summerBody 0; # ==> ::s s 10; # ==> 10 s 5; # ==> 15 s 2; # ==> 17 s 1; # ==> 18 ====== Without `coloop`, you'd need to write something like this: ====== proc summerBody {n} { set x [yield [info coroutine]] while 1 { set x [yield [incr n $x]] } } ====== Which is not much longer, but ''is'' much less clear as to what value is flowing where. With longer bodies, it becomes even less clear. ** Example: `yield` From Any Command in a Coroutine Context ** `yield` can happen in anywhere in a coroutine context, not just in the ''command'' specified as the initial entry point to the `[coroutine]` context. In the following example, `alphadig` is the initial entry point, but `p1` and In the following example, `alpadig` is the initial entry point, but `p1` and ====== proc p1 {} { foreach digit {1 2 3} { yield $digit } p2 } proc p2 {} { foreach digit {4 5 6} { yield $digit } } proc alphadig {} { yield [info coroutine] p1 } set name [coroutine c1 alphadig] while 1 { set res [c1] if {[namespace which c1] eq $name } { puts $res } else { #discard last result, which is the coroutine "falling off the end" rather #than a real value break } } ====== '''Output:''' ======none 1 2 3 4 5 6 ====== <> Command