util.stream
- Stream library ¶This module provides a library of lazy streams, including the
functions and syntaxes defined in SRFI-40 and SRFI-41,
the latter of which became a part of R7RS large (as (scheme stream)
,
Gauche has a built-in lazy sequences (see Lazy sequences), which is a lazy stream integrated to a list so that you can use all list procedures on it. Lazy streams provided in this module are somewhat heavier than lazy sequences and you need to use special procedures, but it is strictly lazy (while a lazy sequence evaluates one element ahead) and portable.
• Stream primitives: | ||
• Stream constructors: | ||
• Stream binding: | ||
• Stream consumers: | ||
• Stream operations: |
[R7RS stream]
{util.stream
}
Returns #t
iff obj is a stream created by a procedure
of util.stream
.
[R7RS stream]
{util.stream
}
The singleton instance of NULL stream.
[R7RS stream]
{util.stream
}
A fundamental constructor of a stream. Adds object to the
head of a stream, and returns a new stream.
[R7RS stream]
{util.stream
}
Returns #t
iff obj is the null stream.
[R7RS stream]
{util.stream
}
Returns #t
iff obj is a non-null stream.
[R7RS stream]
{util.stream
}
Returns the first element of the stream s.
[R7RS stream]
{util.stream
}
Returns the remaining elements of the stream s, as a stream.
[SRFI-40]{util.stream
}
Returns a stream which is a delayed form of expr.
As a rule of thumb, any stream-producing functions should
wrap the resulting expression by stream-delay
.
(Or you can use stream-lambda
, stream-let
or stream-define
,
described below.)
[R7RS stream]
{util.stream
}
A convenience macro to create a function that returns a stream.
Effectively, (stream-lambda formals body body2 …)
is the same
as (lambda formals (stream-delay body body2 …))
.
[SRFI-40]{util.stream
}
Returns a new stream whose elements are obj ….
Note: This differs from SRFI-41’s (scheme.stream
’s) stream
,
which is a macro so that arguments are lazily evaluated. SRFI-41’s
stream
is provided as stream+
in this module.
(stream 1 2 3)) ⇒ a stream that contains (1 2 3) (stream 1 (/ 1 0))) ⇒ error
{util.stream
}
Returns a new stream whose elements are the result of expr ….
This is the same as SRFI-41(scheme.stream
)’s stream
.
Each expr isn’t evaluated until it is accessed.
(define s (stream+ 1 (/ 1 0))) ;; doesn't yield an error
(stream-car s) ⇒ 1
(stream-cadr s) ⇒ error
[R7RS stream]
{util.stream
}
Creates a new stream whose element is determined as follows:
#f
, the stream terminates.
(f s)
is the element of the stream,
and (g s)
becomes the next seed value, where
s
is the current seed value. The initial seed value
is given by seed.
Note: Unfortunately, the order of arguments differs from
other *-unfold
procedures, which takes p f g
(predicate, value-generator and seed-generator). Furthermore,
the predicate is stop-predicate (returning true stops iteration).
(stream->list (stream-unfold integer->char (cut < <> 58) (cut + 1 <>) 48)) ⇒ (#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9)
[SRFI-40]{util.stream
}
Creates n streams related each other, whose contents are
generated by f and seed.
The f is called with the current seed value,
and returns n+1
values:
(f seed) => seed result_0 result_1 ... result_n-1
The first value is to be the next seed value. Result_k must be one of the following forms:
(val)
val will be the next car of k-th stream.
#f
No new information for k-th stream.
()
The end of k-th stream has been reached.
The following example creates two streams, the first one produces an infinite series of odd numbers and the second produces evens.
gosh> (define-values (s0 s1) (stream-unfoldn (lambda (i) (values (+ i 2) ;; next seed (list i) ;; for the first stream (list (+ i 1)))) ;; for the second stream 0 2)) #<undef> gosh> (stream->list (stream-take s0 10)) (0 2 4 6 8 10 12 14 16 18) gosh> (stream->list (stream-take s1 10)) (1 3 5 7 9 11 13 15 17 19)
[R7RS stream]
{util.stream
}
Like stream-unfoldn
, but the number of created streams is
determined by the number fo return values from f. See
stream-unfoldn
above for the details.
[R7RS stream]
{util.stream
}
Returns an infinite stream that repeats obj ….
(stream->list 10 (stream-constant 1 2)) ⇒ (1 2 1 2 1 2 1 2 1 2)
{util.stream
}
Creates a new stream of n elements of init.
If init is omitted, #f
is used.
Specifying a negative number to n creates an infinite stream.
{util.stream
}
Creates a new stream of n elements.
The k-th element is obtained by applying init-proc
to k. Specifying a negative number to n creates
an infinite stream.
{util.stream
}
Creates a new stream of numbers, starting from start
and incrementing step. The length of stream is maximum
integer not greater than nonnegative real number count.
The default values of count
, start and step are
+inf.0
, 0 and 1, respectively.
If start and step are exact, and count is exact or infinite, a sequence of exact numbers are created. Otherwise, a sequence of inexact numbers are created.
[R7RS stream]
{util.stream
}
Creates a new stream of real numbers, starting from start
and stops before end, stepping by step.
If end is omitted, positive infinity is assumed.
If step is omitted, 1
is assumed if end is greater
than start, and -1
if end is less than start.
The generated numbers are exact if start and step are exact and end is either exact or infinite. Otherwise, inexact numbers are generated.
In R7RS scheme.stream
, end argument is required.
(stream->list (stream-range 0 10)) ⇒ (0 1 2 3 4 5 6 7 8 9)
[R7RS stream]
{util.stream
}
This is yet another number sequence generator. Generates an infinite
sequence whose i-th element is (+ start (* i step))
.
If step is omitted, 1 is assumed. If both start and step
are exact, exact numbers are generated. Otherwise, inexact numbers are
generated.
[R7RS stream]
{util.stream
}
Returns a stream starting from seed, and each successive element
is calculated by (f s)
where s is the previous
element.
(stream->list 5 (stream-iterate (cut cons 'x <>) '())) ⇒ (() (x) (x x) (x x x) (x x x x))
See also literate
in gauche.lazy
(see gauche.lazy
- Lazy sequence utilities).
{util.stream
}
(stream-cons b a)
. Just for convenience.
{util.stream
}
Creates a new stream which appends elt … before stream.
[R7RS stream]
{util.stream
}
Returns a new stream whose elements are the elements in list.
{util.stream
}
Converts a string to a stream of characters. If an optional
tail-stream is given, it becomes the tail of the resulting
stream.
(stream->list (string->stream "abc" (list->stream ’(1 2 3)))) ⇒ (#\a #\b #\c 1 2 3)
{util.stream
}
Returns a stream which is a result of applying string->stream
to (format fmt arg …)
.
[R7RS stream]
{util.stream
}
Creates a stream, whose elements consist of the items
read from the input port iport.
The default iport is the current input port.
The default reader is read-char
.
The result stream terminates at the point where reader returns EOF (EOF itself is not included in the stream). The port won’t be closed by default when it reaches EOF.
If closer is given, it is called with iport as an argument just after reader reads EOF. You can close the port with it.
The reader and closer arguments are Gauche’s extension.
R7RS scheme.stream
only takes one optional argument, iport.
{util.stream
}
Creates a lazy stream of values generated by a generator gen.
A generator is a thunk that returns a value every time it is called,
with returning EOF to indicate the end of the input.
See gauche.generator
- Generators, for the details of generators.
See also generator->lseq
, which is another way to get
a lazy sequence from a generator (see Lazy sequences, for the details).
{util.stream
}
A generic procedure to turn an internal iterator iter
into a stream of iterated results.
The iter argument is a procedure that takes two arguments, next and end, where next is a procedure that takes one argument and end is a thunk. Iter is supposed to iterate over some set and call next for each argument, then call end to indicate the end of the iteration. Here’s a contrived example:
(stream->list (iterator->stream (lambda (next end) (for-each next '(1 2 3 4 5)) (end)))) ⇒ (1 2 3 4 5)
Internally iterator->stream
uses the “inversion of iterator”
technique, so that iter only iterates to the element that
are needed by the stream. Thus iter can iterate over
an infinite set. In the following example, iter is
an infinite loop calling next with increasing integers,
but only the first 10 elements are calculated because of
stream-take
:
(stream->list (stream-take (iterator->stream (lambda (next end) (let loop ((n 0)) (next n) (loop (+ n 1))))) 10)) ⇒ (0 1 2 3 4 5 6 7 8 9)
[R7RS stream]
{util.stream
}
Stream comprehension. Returns a stream in which each element
is computed by elt-expr.
The clause creates scope of elt-expr
and controls iterations. Each clause can be one of the following
forms:
(x in stream-expr)
Iterate over stream-expr, binding x to each element in each iteration. The variable x is visible in successive clauses and elt-expr
(x is expr)
Bind a variable x with the value of expr. The variable x is visible in successive clauses and elt-expr.
expr
If expr evaluates to #f
, this iteration is skipped without
generating a new element.
The following comprehension generates infinite sequence of pythagorean triples:
(define pythagorean-triples (stream-of (list a b c) (c in (stream-from 3)) (b in (stream-range 2 c)) (a in (stream-range 1 b)) (= (square c) (+ (square b) (square a))))) (stream->list 5 pythagorean-triples) ⇒ ((3 4 5) (6 8 10) (5 12 13) (9 12 15) (8 15 17))
[R7RS stream]
{util.stream
}
A convenient macro to define a procedure that yields a stream.
Same as the following form:
(define (name . formals) (stream-delay (let () body body2 ...)))
[R7RS stream]
{util.stream
}
A handy macro to write a lazy named-let loop. It is the same as the
following:
(let loop-var ((var init) ...) (stream-delay (let () body body2 ...)))
[R7RS stream]
{util.stream
}
This allows accessing streams via simple pattern matching.
The stream-expr argument is evaluated and must yield a stream.
Each clause
must be either a form of (pattern expr)
or
(pattern fender expr)
.
The content of the stream is matched to each pattern, which must have one of the following forms:
()
Matches a null stream.
(p0 p1 …)
Matches a stream that has exactly the same number of elements as the number of pattern elements.
(p0 p1 … . pRest)
Matches a stream that has at least the same number of elements as the number of pattern elements except pRest. The rest of stream matches with pRest.
pRest
Matches an entire stream.
Each pattern element can be an identifier or a literal underscore. If it is an identifier, it is bound to the matched element while evaluating the corresponding fender and expr.
If fender is present in the clause, it is evaluated; if
it yields #f
, the match of the clause fails and next clauses will be
tried.
Otherwise, expr is evaluated and the result(s) becomes the result(s)
of stream-match
.
Only the elements from the stream that is required to match are accessed.
The following example defines a procedure to count the number of true values in the stream:
(define (num-trues strm) (stream-match strm (() 0) ((head . tail) head (+ 1 (num-trues tail))) ((_ . tail) (num-trues tail)))) (num-trues (stream #f #f #t #f #t #f #t #t)) ⇒ 4
These procedures takes stream(s) and consumes its/their elements until one of the streams is exhausted.
[R7RS stream]
{util.stream
}
Applies func for each element of streams.
Terminates if one of streams reaches the end.
[R7RS stream]
{util.stream
}
Apply f on the current seed value and an element from
stream to obtain the next seed value, and repeat it until
stream is exhausted, then returns the last seed value.
The initial seed value is given by seed.
Note: The argument order of f differs from other *-fold
procedures, e.g. fold
(see Walking over lists) takes
the element first, then the seed value.
(stream-fold - 0 (stream 1 2 3 4 5)) ⇒ -15
[R7RS stream]
{util.stream
}
Returns a new stream which is concatenation of given streams.
[R7RS stream]
{util.stream
}
R7RS scheme.stream
defines stream-concat
. Gauche had
stream-concatenate
, and keeps it for the backward compatibility.
Both are the same.
The streams argument is a stream of streams. Returns a new stream
that is concatenation of them. Unlike stream-append
, streams
can generate infinite streams.
[R7RS stream]
{util.stream
}
Returns a new stream, whose elements are calculated by
applying func to each element of stream ….
[R7RS stream]
{util.stream
}
Returns a stream of seed
, (func seed e0)
,
(func (func seed e0) e1)
, …, where
e0, e1 … are the elements from the input stream.
If stream is finite, the result stream has one more elements than
the number of elements in the original stream.
(stream->list (stream-scan xcons '() (stream 1 2 3 4 5))) ⇒ (() (1) (2 1) (3 2 1) (4 3 2 1) (5 4 3 2 1))
[R7RS stream]
{util.stream
}
Returns a new stream whose elements are lists of corresponding
elements from input streams. The output stream ends
when one of input streams is exhausted.
(stream->list (stream-zip (stream 1 2 3) (stream 'a 'b 'c 'd))) ⇒ ((1 a) (2 b) (3 c))
[R7RS stream]
{util.stream
}
Returns a new stream including only elements passing pred.
This procedure returns immediately; stream can be infinite.
{util.stream
}
Returns a new stream including only elements that doesn’t satisfy pred.
It is the same as (stream-filter (complement pred) stream)
.
{util.stream
}
Returns two streams, one consists of the elements in stream
that satisfy pred, the other consists of the ones that doesn’t
satisfy pred.
[R7RS stream]
{util.stream
}
Converts a stream to a list. In the first form, all elements from
stream are taken (thus it never returns if stream is infinite).
In the second form, at most n elements are taken, where
n must be a nonnegative exact integer.
Note: In usual Scheme conventions, the optional n comes after the main argument (stream).
{util.stream
}
Converts a stream to a string.
All elements of stream must be characters, or an error is signaled.
{util.stream
}
Splits stream where its element equals to #\n
, and
returns a stream of splitted streams. The character #\n
won’t
be included in the results.
(stream->list (stream-map stream->string (stream-lines (string->stream "abc\ndef\nghi")))) ⇒ ("abc" "def" "ghi")
{util.stream
}
Returns true iff each corresponding element of stream …
are the same in terms of elt=, which takes two arguments.
This procedure won’t terminate
if all of streams is infinite.
{util.stream
}
Compares initial elements of stream against
a list prefix by elt=. Returns true iff they match.
Only as many elements of stream
as prefix has are checked.
{util.stream
}
(stream-caar s)
= (stream-car (stream-car s))
etc.
[R7RS stream]
{util.stream
}
Returns the pos-th element in the stream. Pos
must be a nonnegative exact integer.
{util.stream
}
(stream-first s)
= (stream-ref s 0)
etc.
{util.stream
}
Returns a new stream that consists of the first count elements
of the given stream. If the given stream has less than
count elements, the stream returned by stream-take
would raise an error when the elements beyond the original stream
is accessed. On the other hand, the stream returned by
stream-take-safe
will return a shortened stream when
the given stream has less than count elements.
(stream->list (stream-take (stream-iota -1) 10)) ⇒ (0 1 2 3 4 5 6 7 8 9) (stream-take (stream 1 2) 5) ⇒ stream (stream->list (stream-take (stream 1 2) 5)) ⇒ error (stream->list (stream-take-safe (stream 1 2) 5)) ⇒ (1 2)
Note: SRFI-41 (scheme.stream
) also defines stream-take
, but
the argument order is reversed, and also it allows stream to have
less than count
elements.
{util.stream
}
Returns a new stream that consists of the elements in the given
stream except the first count elements.
If the given stream has less than count elements,
stream-drop
returns a stream that raises an error
if its element is accessed, and stream-drop-safe
returns an empty stream.
Note: SRFI-41 (scheme.stream
) also defines stream-drop
, but
the argument order is reversed, and also it allows stream to have
less than count
elements.
{util.stream
}
Returns a new stream in which element is
inserted between each consecutive two elements of stream.
(stream->list (stream-intersperse (stream 1 2 3) 0)) ⇒ (1 0 2 0 3)
{util.stream
}
Split stream on elements that satisfy pred,
and returns a stream of splitted streams. The delimiting element
won’t be included in the result.
(stream->list (stream-map stream->list (stream-split (stream 1 3 2 5 7 9 6 8 1) even?)))) ⇒ ((1 3) (5 7 9) () (1))
{util.stream
}
Returns the last element of stream.
If stream is empty, an error is thrown.
If stream is infinite, this procedure won’t return.
{util.stream
}
Returns a stream that contains the last count elements
in stream. The count argument must be a nonnegative exact
integer. If the length of stream is smaller than count,
the resulting stream is the same as stream.
If stream is infinite,
this procedure won’t return.
{util.stream
}
Returns a stream which is the same as stream but without the
last element. If stream is empty, an empty stream is returned.
immediately. The argument can be an infinite stream.
{util.stream
}
Returns a stream which is the same as stream but without the
last count elements. The count argument must be a nonnegative exact
integer. If stream is shorter than count, a null stream
is returned. Stream can be infinite.
[R7RS stream]
{util.stream
}
Returns the number of elements in stream.
It diverges if stream is infinite.
{util.stream
}
Returns true iff the length of stream is greater than or equal to,
and exactly equal to, n, respectively.
These procedures only realizes stream up to n elements.
[R7RS stream]
{util.stream
}
Returns a stream that returns the elements of stream in reverse order.
If tail-stream is given, it is added after the reversed stream.
The optional argument is Gauche’s extension. The description of reverse
(see Other list procedures) for more details.
{util.stream
}
The predicate pred is called with each of the first element of
stream …, then each of the second element, and so on, until
any of the stream is exhausted. Then returns the number that
pred returns a true value.
At least one stream needs to be finite.
(stream-count < (stream 1 2 3 4 5) (stream 2 2 2 10 10)) ⇒ 3
{util.stream
}
The predicate pred is applied to each element of stream in turn,
and as soon as the pred returns true, returns the element that
caused pred to return true. Remaining elements of stream
won’t be realized.
If no elements in stream satisfy pred, #f
is returned.
{util.stream
}
The predicate pred is applied to each element of stream in turn,
and as soon as the pred returns true, returns a stream
that contains the element and the rest of the input stream.
Remaining elements of stream won’t be realized.
If no elements in stream satisfy pred, the empty stream is returned.
[R7RS stream]
{util.stream
}
Returns a stream that contains or excludes initial consecutive elements
of stream that satisfy pred, respectively.
(stream->list (stream-take-while even? (stream 2 4 6 1 4 2))) ⇒ (2 4 6) (stream->list (stream-drop-while even? (stream 2 4 6 1 4 2))) ⇒ (1 4 2)
{util.stream
}
Return two streams; the first one consists of the initial consequent
elements of stream that satisfy or dissatisfy pred,
and the second one is the rest of the stream.
(map stream->list (values->list (stream-span even? (stream 2 4 6 1 4 2)))) ⇒ ((2 4 6) (1 4 2)) (map stream->list (values->list (stream-break even? (stream 1 9 6 1 4 2)))) ⇒ ((1 9) (6 1 4 2))
{util.stream
}
The predicate pred is applied to each of the first elements of
stream …, then second, and so on.
When pred returns a true value, stream-any
returns
the value immediately without looking further.
When pred returns #f
, stream-every
returns #f
immediately without looking further.
If none of applications of pred returns a true value
until one of the streams is exhausted, stream-any
returns #f
.
If none of applications of pred returns #f
until one of the streams is exhausted, stream-every
returns
the last result of pred.
(stream-any (^[x y] (and (> x y) (list x y))) (stream 1 2 3 4 5) (stream 3 3 3 3 3)) ⇒ (4 3) (stream-every (^[x y] (and (> x y) (list x y))) (stream 6 6 6 6 6) (stream 1 2 3 4 5)) ⇒ (6 5)
{util.stream
}
The predicate pred is applied to each of the first elements of
stream …, then second, and so on. If it returns a true
value, stream-index
returns immediately with the index.
If pred never returns a true value until one of
the streams is exhausted, stream-index
returns #f.
(stream-index odd? (stream 2 4 6 7 8)) ⇒ 3
{util.stream
}
Stream version of member
, memq
, and memv
(see Other list procedures). Search an element equivalent to
obj from stream, and if it is found, returns a stream
consists of the element and the rest of the stream.
If no such element is found, #f
is returned.
They differ regarding which equivalent procedure to be used;
stream-member
uses the given elt= procedure, or equal?
if omitted, stream-memq
uses eq?
, and stream-memv
uses eqv?
.
{util.stream
}
Equivalent to (stream-remove (cut elt= obj <>) stream)
, that is,
returns a stream that is the same as input except objs.
If elt= is omitted, equal?
is used.
{util.stream
}
Returns a stream that is the same as input except the consecutive
equivalent elements are removed but the first one.
Elements are compared with elt=, defaulted to equal?
.
{util.stream
}
The re argument must be a regexp object, or a string representation
of regexp (which is converted to regexp by string->regexp
).
Returns a stream that contains input elements that matches re.
{util.stream
}
Writes each element of stream to oport, using writer.
When oport is omitted, the current output port is used.
When writer is omitted, write-char
is used.
No ’spacer’ is written between elements. As the default suggests, this is most useful to write out a stream of characters.