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!