Version 4 of yield

Updated 2009-12-28 19:21:49 by dkf

Consequence of NRE, see coroutine.

yield ?value?

DKF: Can also be thought of as a magical form of return. That returns itself (possibly).


DKF: If you're trying to build a coroutine that yields many 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 variable 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.