chickadee » srfi-40

SRFI 40: A Library of Streams


A Chicken implementation of SRFI 40.


stream-null is the distinguished nil stream, a single Scheme object distinguishable from all other objects. If the last stream-pair in a stream contains stream-null in its cdr field, the stream is finite and has a computable length. However, there is no need for streams to terminate.

stream-null                                 => (stream)
stream-cons object streamprocedure

stream-cons is the primitive constructor of streams, returning a stream with the given object in its car field and the given stream in its cdr field. The stream returned by stream-cons must be different (in the sense of eqv?) from every other Scheme object. The object may be of any type, and there is no requirement that successive elements of a stream be of the same type, although it is common for them to be. It is an error if the second argument of stream-cons is not a stream.

(stream-cons 'a stream-null)                => (stream 'a)
(stream-cons 'a (stream 'b 'c 'd))          => (stream 'a 'b 'c 'd)
(stream-cons "a" (stream 'b 'c))            => (stream "a" 'b 'c)
(stream-cons 'a 3)                          => error
(stream-cons (stream 'a 'b) (stream 'c))    => (stream (stream 'a 'b) 'c)
stream? objectprocedure

stream? returns #t if the object is a stream, and otherwise returns #f. A stream object may be either the null stream or a stream pair created by stream-cons.

(stream? stream-null)                       => #t
(stream? (stream-cons 'a stream-null))      => #t
(stream? 3)                                 => #f
stream-null? objectprocedure

stream-null? returns #t if the object is the distinguished nil stream, and otherwise returns #f

(stream-null? stream-null) => #t
(stream-null? (stream-cons 'a stream-null)) => #f
(stream-null? 3) => #f
stream-pair? objectprocedure

stream-pair? returns #t if the object is a stream pair created by stream-cons, and otherwise returns #f.

(stream-pair? stream-null)                  => #f
(stream-pair? (stream-cons 'a stream-null)) => #t
(stream-pair? 3)                            => #f
stream-car streamprocedure

stream-car returns the object in the stream-car field of a stream-pair. It is an error to attempt to evaluate the stream-car of stream-null.

(stream-car (stream 'a 'b 'c))              => a
(stream-car stream-null)                    => error
(stream-car 3)                              => error
stream-cdr streamprocedure

stream-cdr returns the stream in the stream-cdr field of a stream-pair. It is an error to attempt to evaluate the stream-cdr of stream-null.

(stream-cdr (stream 'a 'b 'c))              => (stream 'b 'c)
(stream-cdr stream-null)                    => error
(stream-cdr 3)                              => error
stream-delay expressionprocedure

stream-delay is the essential mechanism for operating on streams, taking an expression and returning a delayed form of the expression that can be asked at some future point to evaluate the expression and return the resulting value. The action of stream-delay is analogous to the action of delay, but it is specific to the stream data type, returning a stream instead of a promise; no corresponding stream-force is required, because each of the stream functions performs the force implicitly.

(define from0
  (let loop ((x 0))
      (stream-cons x (loop (+ x 1))))))
from0                                       => (stream 0 1 2 3 4 5 6 ...)
stream object ...procedure

stream returns a newly allocated finite stream of its arguments, in order.

(stream 'a (+ 3 4) 'c)                      => (stream 'a 7 'c)
(stream)                                    => stream-null
stream-unfoldn generator seed nprocedure

stream-unfoldn returns n streams whose contents are produced by successive calls to generator, which takes the current seed as an arguments and returns n + 1 values:

    (proc seed) -> seed result0 ... resultN

where resultI indicates how to produce the next element of the Ith result stream:

value is the next car of this result stream
no new information for this result stream
the end of this result stream has been reached

Note that getting the next element in any particular result stream may require multiple calls to generator.

(define (take5 s)
    (lambda (x)
      (let ((n (car x)) (s (cdr x)))
        (if (zero? n)
            (values 'dummy '())
              (cons (- n 1) (stream-cdr s))
              (list (stream-car s))))))
    (cons 5 s)
(take5 from0)                              => (stream 0 1 2 3 4)
stream-map function stream ...procedure

stream-map creates a newly allocated stream built by applying function elementwise to the elements of the streams. The function must take as many arguments as there are streams and return a single value (not multiple values).

The stream returned by stream-map is finite if the given stream is finite, and infinite if the given stream is infinite.

If more than one stream is given, stream-map terminates when any of them terminate, or is infinite if all the streams are infinite. The stream elements are evaluated in order.

(stream-map (lambda (x) (+ x x)) from0)      => (stream 0 2 4 6 8 10 ...)
(stream-map + (stream 1 2 3) (stream 4 5 6)) => (stream 5 7 9)
(stream-map (lambda (x) (expt x x))
  (stream 1 2 3 4 5))                        => (stream 1 4 27 256 3125)
stream-for-each procedure stream ...procedure

stream-for-each applies procedure elementwise to the elements of the streams, calling the procedure for its side effects rather than for its values. The procedure must take as many arguments as there are streams. The value returned by stream-for-each is unspecified. The stream elements are visited in order.

(stream-for-each display from0)             => no value, prints 01234 ...
stream-filter predicate? streamprocedure

stream-filter applies predicate? to each element of stream and creates a newly allocated stream consisting of those elements of the given stream for which predicate? returns a non-#f value. Elements of the output stream are in the same order as they were in the input stream, and are tested by predicate? in order.

(stream-filter odd? stream-null)            => stream-null
(take5 (stream-filter odd? from0))          => (stream 1 3 5 7 9)

Other procedures

For unclear reasons, the following procedures are also exposed:

make-s:promise make-stream make-box srfi-40:eager stream-error

These should probably not be used by programs.


Philip L. Bewig, ported to hygienic CHICKEN with test suite by Peter Danenberg


Artistic license

Contents »