Consumers for generators
I've been trying out generators for
day-to-day scripts and have repeatedly seen a common pattern---
to repeat reading from a generator and process values until it
I wrote a bunch of utilities
gauche.generator but they are mostly a sort of filters,
taking generators and yielding another generator. What I needed
is a kind of "terminator" of the chain of generators, where
the generated values were actually consumed.
Since a generator is just a thunk, I can use already existing
expect thunks (in spite of their names), and we can pass
a generator directly.
(port-for-each (^v ...) generator-expr)
Probably I should rename them to indicate they are actually about generators, not ports.
(Another option is to convert a generator to a lazy sequence
generator->lseq, so that we can use all list-handling
utilities without wasting space for intermediate lists. But it
still has some overhead (not only CPU-wise, but mentally for
programmers who read and write the code). So I think it makes
sense to have specialized utilities for generators.)
For lists, we have
for-each. But sometimes it is handy
and more readable to use
dolist macro, taken from CL.
We can have its equivalent for generators:
(do-generator [v generator-expr] ... do something with v ...)
What if we want to run across multiple generators, or
even to mix generators and other sequences? Instead of
inventing more macros, we can extend the existing
mechanism to handle generators.
(do-ec (:parallel (: x '(a b c)) (: y (gdrop-while skip-preamble (file->generator "foo")))) (do-something x y))
For the latter, we added :generator EC-qualifier (so the second
:parallel in the above example can also be written as
(:generator y ...)). The generic
: dispatches to the
its argument is an applicable entity taking zero arguments.
Those changes have been pushed to the master.