Name: Anonymous 2005-12-21 8:09
Because I'm learning it, almost done through the tutorial, and it looks great.
call/cc. I was asking for how to do it using delimited continuations, more specifically, using shift/reset. Since delimited continuations may be used to implement call/cc, it comes as no surprise that (make-generator f) may be implemented using delimited continuations. However, I would like to know the most natural way of doing it, preferably without wrapping the code in a reset (which would amount to emulating call/cc, which involves an unfortunate copying of the entire stack).
yield procedure, instead of passing it as an argument, but that's doable too.
(define (yield . xs)
(shift k (cons k xs)))
(define ((generator f) . xs)
(reset (apply f xs) #f))
(define ((generator/yield-arg f) . xs)
(reset (f yield) #f))
(define ((fioc-generator-of gen) f)
(let ((g (gen f)))
(lambda ()
(let ((next (g)))
(set! g (car next))
(apply values (cdr next))))))
(define fioc-generator (fioc-generator-of generator))
(define fioc-generator/yield-arg (fioc-generator-of generator/yield-arg))
(define g
(fioc-generator
(lambda ()
(for-each yield '(1 2 3 4)))))
(g) ; 1
(g) ; 2
(g) ; 3
(define g2
(generator/yield-arg
(lambda (yield)
(for-each yield '(1 2 3 4)))))
(g2) ; (cont . (1))
((car (g2))) ; (cont . (2))
((car ((car (g2))))) ; (cont . (3))
((car (g2))) ; (cont . (2))
(define g3
(fioc-generator/yield-arg
(lambda (yield)
(for-each yield '(1 2 3 4)))))
(g3) ; 1
(g3) ; 2
(g3) ; 3
yield procedure, instead of passing it as an argument, but that's doable too.(f yield) directly, without wrapping it using (make-generator f), in order to call (yield x) on every generated element of f. Whether this is actually useful is arguable.
yield escapes its generator procedures' dynamic extent, bad things can happen:reset, returning '(cont . args).