[plt-scheme] understanding make-do-sequence
It appears that `make-do-sequence' avoids applying the first procedure
(the pos->element one) if certain other procedures indicate the sequence
is finished. This is important to the client in the case where that
procedure has side effects.
Consider a sequence generator `in-port-until':
;; a * (a -> b1 .. bn) (a -> boolean) -> (sequenceof b1 .. bn)
(define (in-port-until port reader done?)
(make-do-sequence (lambda ()
(values reader
(lambda (port) port)
port
(lambda (port)
(not (done? port)))
values
(lambda (port . values) #t)))))
and a use case like:
> (define p (open-input-string "xxxxy"))
> (define (no-more-xs? port)
(not (char=? (peek-char port) #\x)))
> (for/list ([x (in-port-until p read-char no-more-xs?)])
x)
(#\x #\x #\x #\x)
> (read-char p)
#\y
That last line is the critical one: if `in-port' had caused `read-char'
to be called the extra time, it would've silently eaten the last #\y
char, and the last line would've returned #<eof>.
This seems pretty subtle. I don't know if a cleaner API is possible, but
it at least bears documenting exactly when the pos->element will and
won't be applied.
Thanks,
Dave