[plt-scheme] Re: yield-oriented sequence constructor

From: Doug Orleans (dougorleans at gmail.com)
Date: Sat Mar 22 23:03:48 EDT 2008

Eli Barzilay writes:
 > On Mar 21, Doug Orleans wrote:
 > > 
 > > Here's a much simpler version of make-yield-sequence, though it
 > > seems kinda like voodoo to me.  I'm wondering if I can just lift
 > > this yield to the top level and get rid of the parameter altogether,
 > > but then how do I install the default behavior in a top-level
 > > prompt?
 > Seems like voodoo to me too, but is there really a need for a
 > parameter?

The parameter is just for dynamic scoping, so you don't need to
explicitly parameterize your code over a yield procedure.  Also it's
nice that the default yield just prints the values (using
current-print), as if you had returned them to the repl.
If you get rid of the parameter, it doesn't look much different:

(define (make-yield-sequence fun)
  (define (yield . vals) (control k (cons k vals)))
   (lambda ()
      (lambda (pos) (apply values (cdr pos)))
      (lambda (pos) (prompt ((car pos))))
      (prompt (fun yield) #f)
      values void void))))

 > BTW, there is a `function-iterator' in Swindle, which sort of
 > translates to this (modulo the voodooness, so I won't be surprised if
 > this is doing something horribly wrong):
 >   (define (iter fun finally)
 >     (define (yield v) (control k (set! cont (lambda () (k (void)))) v))
 >     (define (cont) (fun yield) finally)
 >     (lambda () (prompt (cont))))

The thing that seems like voodoo to me in my version is that there's
no mutation involved: instead of setting the continuation thunk, it
returns the continuation (along with the values) to the current
prompt, becoming the sequence position, and then when the next
position is needed it wraps the continuation call in a new prompt.
(If you squint it's sort of like client-side continuations in the
web-server!)  I guess the difference is that your "iter" is more like
a generator, which has state; if I used sequence-generate to make a
generator out of my sequence, that would be using mutation inside too.

> (define-values (more? next)
    (sequence-generate (in-yields (yield-each '(1 2 3)))))
> (next)
> (next)
> (next)
> (next)
sequence has no more values

 === context ===

--dougorleans at gmail.com

Posted on the users mailing list.