gauche.lazy- Lazy sequence utilities
This module provides utility procedures that yields lazy sequences. For the details of lazy sequences, see Lazy sequences.
Since lazy sequences are forced implicitly and indistinguishable
from ordinary lists, we don’t need a separate set of procedures
for taking lists and lazy sequences; we can use
to search in both ordinary lists and lazy sequences.
However, we do need a separate set of procedures for returning either lists or lazy sequences. For example, lmap can take any kind of sequences, and returns lazy sequence (and calls the procedure on demand).
This distinction is subtle, so I reiterate it. You can use
lmap on lazy sequences. If you want
the result list at once, use
map; it doesn’t have
overhead of delayed calculation. If you don’t know you’ll use
the entire result, or you know the result will get very large
list and don’t want to waste space for an intermediate list,
you want to use
A convenience function to coerce obj to (possibly lazy) list. If obj is a list, it is returned as it is. If obj is other type of collection, the return value is a lazy sequence that iterates over the collection.
If you try
x->lseq in REPL, it looks as if it just
converts the input collection to a list.
(x->lseq '#(a b c)) ⇒ (a b c)
But that’s because the lazy sequence is forced by the output routine of the REPL.
A lazy version of
unfold (see SRFI-1 List utilities).
The arguments p, f and g are procedures,
each of which take one argument, the current seed value.
The predicate p determines when to stop, f creates
each element, and g generates the next seed value.
The seed argument gives the initial seed value.
If tail-gen is given, it should also be a procedure
that takes one argument, the last seed value (that is, the
(p seed) returned
#f). It must return
a (possibly lazy) list, that forms the tail of the resulting sequence.
(lunfold ($ = 10 $) ($ * 2 $) ($ + 1 $) 0 (^_ '(end))) ⇒ (0 2 4 6 8 10 12 14 16 18 end)
Returns a lazy sequence consists of values calculated
by applying proc to every first element of seq
…, every second element of them, etc., until any of
the input is exhausted.
The procedure proc takes one element each from
seq seq2 …, plus the current seed value.
It must return two values, a result value and the next seed value.
The result of
lmap-accum is a lazy sequence consists
of the first values returned by each invocation of proc.
This is a lazy version of
map-accum (see Mapping over collection),
lmap-accum does not return the final seed value. We only
know the final seed value when we have the result sequence to the
end, so it can’t be calculated lazily.
Returns a lazy sequence consists of elements in seq ….
The seqs argument is a sequence of sequences. Returns a lazy sequence that is a concatenation of all the sequences in seqs.
This differs from
(apply lappend seqs), for
can handle infinite number of lazy seqs.
Lazy version of
append-map. This differs not only from
(apply lappend (lmap proc seq1 seq …)), which would
evaluate the result of
lmap to the end before passing it to
lappend, but also differ from
(lconcatenate (lmap proc seq1 seq …)) in the subtle way.
Remember that Gauche’s lazy sequence evaluates one element ahead?
lconcatenate does that to the result of
To see the effect, let’s define a procedure with a debug print:
(define (p x) #?=(list x x))
You can see that
(apply lappend (lmap ...)) wouldn’t delay
any of application of
gosh> (car (apply lappend (lmap p '(1 2 3)))) (car (apply lappend (lmap p '(1 2 3)))) #?="(standard input)":4:(list x x) #?- (1 1) #?="(standard input)":4:(list x x) #?- (2 2) #?="(standard input)":4:(list x x) #?- (3 3) 1
gosh> (car (lconcatenate (lmap p '(1 2 3)))) (car (lconcatenate (lmap p '(1 2 3)))) #?="(standard input)":4:(list x x) #?- (1 1) #?="(standard input)":4:(list x x) #?- (2 2) 1
Oops, even though we need only the first element, and the first
(1 1), provides the second element, too,
p is already applied to the second input.
This is because the intermediate lazy list of the result of
evaluated “one element ahead”. On the other hand,
doesn’t have this problem.
gosh> (car (lappend-map p '(1 2 3))) (car (lappend-map p '(1 2 3))) #?="(standard input)":4:(list x x) #?- (1 1) 1
Returns a lazy seq of the first items from seq …, then
their second items, and so on. If the length of shortest sequence
of seqs is N, the length of the resulting sequence is
(* N number-of-sequences). If all of seqs are infinite,
the resulting sequence is also infinite.
(linterweave (lrange 0) '(a b c d e) (circular-list '*)) ⇒ (0 a * 1 b * 2 c * 3 d * 4 e *)
Returns a lazy sequence that consists of non-false values calculated by applying proc on every elements in seq.
Lazy version of
Lazy version of
Lazy versions of
(see List accessors and modifiers). Note that
ltake works rather like
that is, it won’t complain if the input sequence has less than n
elements. Because of the lazy nature of
ltake, it can’t know
whether input is too short or not before returning the sequence.
There are no
ldrop-while; if you apply
drop-while on lazy sequence, they return
This is a lazy sequence version of
(see Generator operations).
The seq argument must be a sequence of characters. The return value is a lazy sequence of <rxmatch> objects, each representing strings matching to the regular expression rx.
This procedure is convenient to scan character sequences from
lazy character sequences, but it may be slow if you’re looking for
rarely matching string from very large input. Unless seq
is a string,
lrxmatch buffers certain
Lazy version of
slices (see List accessors and modifiers).
(lslices '(a b c d e f) 2) ⇒ ((a b) (c d) (e f))