On the other hand, if `gpeek` returned three values, the procedure `foo` would instead be written as:
(define (foo gen peek poke)
(if (peek) (gen) 'false-value-in-generator))
Here, everything is code-flow driven and no dispatch is needed making it as fast as it can get.
That is compelling. However, I have thought of a counterargument.
With the current design, it is possible to pass the generator around the code and use it like any other generator until it is necessary to peek or poke it. It is a sort of environment monad, carrying the peek and poke behaviors along with it. This is similar to the way in which `peek-char` works. With your design, the peek and poke procedures would have to be threaded through code that has no interest in them, and (like Mr. Darcy's good opinion) "once lost [are] lost forever".
Matters are simpler for ports than for generators, because a port is a disjoint object with all kinds of private state, and so it is practical to have a global `peek-char` procedure that invokes the proper operation in whatever sort of input port. Unfortunately, a generator is a procedure, and the only thing you can (portably) do with a procedure is invoke it, so there needs to be a public protocol for how peeking and poking are performed. If you can think of any way around this, it would be great.
John Cowan
http://vrici.lojban.org/~cowan xxxxxx@ccil.org"The serene chaos that is Courage, and the phenomenon of Unopened
Consciousness have been known to the Great World eons longer than Extaboulism."
"Why is that?" the woman inquired.
"Because I just made that word up", the Master said wisely.
--Kehlog Albran, The Profit