The scheme/generator library has now some extended functionality in svn, and is included in last night's build:
* `yield' can accept any number of values: -> (define g (generator (yield 1 2))) -> (g) 1 2 * The generator function itself can accept values, which are sent back to the generator as the result of the `yield' call: -> (define g (generator (printf "Got ~s\n" (yield 1 2)) 3)) -> (g) 1 2 -> (g 4) Got 4 3 -> (g) 3 This is similar to using g.send() in python -- and in a similar way, you get: -> (define g (generator (yield 1))) ;; at this point, the generator didn't start running yet, so there ;; is no `yield' expression waiting for a result: -> (g 2) generator: cannot send a value to a fresh generator -> (g) 1 ;; the generator used `yield' to return 1, and it is now ;; suspended, waiting for a result of that expression, `g' can be ;; used to return such a result (with any number of values): -> (g 2) 2 ;; so the generator is now terminated -- the last value in its ;; body is the result of that `yield' which is the 2 that was sent ;; to it -- and that value is now repeated for ever: -> (g) 2 -> (g) 2 ;; this state is similar to the initial state: there is no `yield' ;; expression waiting for an answer: -> (g 3) generator: cannot send a value to a done generator * This is related to a possibly confusing situation: -> (define g (generator (yield 1) (yield 2))) -> (list (g) (g)) (1 2) -> (list (g)) context expected 1 value, received 0 values The reason for that error is that the third (g) call provides the values that result from the second `yield' expression -- and since that expression is the last in the generator's body, those values are what gets returned from this point on. So: -> (define g (generator (yield 1) (yield 2))) -> (list (g) (g) (g 99)) (1 2 99) Note also the confusing off-by-one differnce: the first (g) starts the generator, the second one provides the result for the first `yield' etc. Here's a toy delay thing: -> (define g (generator (let loop ([x 1] [y 2]) (loop y (yield x))))) -> (g) 1 -> (g 3) 2 -> (g 4) 3 -> (g 5) 4 * Finally, since it is useful to know what state the generator is in, there is a new `generator-state' function: -> (define g (generator (yield 1) (yield 2))) -> (generator-state g) fresh -> (g) 1 -> (generator-state g) suspended -> (g) 2 -> (generator-state g) suspended -> (g) -> (generator-state g) done -> (define g (generator ((yield 1)))) -> (g) 1 -> (g (lambda () (generator-state g))) running -> (generator-state g) done -> (g) ; since it's done, it repeats this forever running -- ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay: http://barzilay.org/ Maze is Life! _________________________________________________ For list-related administrative tasks: http://list.cs.brown.edu/mailman/listinfo/plt-dev