4.17.2 Streams
A stream is a kind of sequence that supports functional iteration via stream-first and stream-rest. The stream-cons form constructs a lazy stream, but plain lists can be used as streams, and functions such as in-range and in-naturals also create streams.
(require racket/stream) | package: base |
procedure
(stream-empty? s) → boolean?
s : stream?
procedure
(stream-first s) → any
s : (and/c stream? (not/c stream-empty?))
procedure
(stream-rest s) → stream?
s : (and/c stream? (not/c stream-empty?))
syntax
(stream-cons first-expr rest-expr)
(stream-cons #:eager first-expr rest-expr) (stream-cons first-expr #:eager rest-expr) (stream-cons #:eager first-expr #:eager rest-expr)
If first-expr is not preceded by #:eager, then first-expr is not evaluated immediately. Instead, stream-first on the result stream forces the evaluation of first-expr (once) to produce the first element of the stream. If evaluating first-expr raises an exception or tries to force itself, then an exn:fail:contract exception is raised, and future attempts to force evaluation will trigger another exception.
If rest-expr is not preceded by #:eager, then rest-expr is not evaluated immediately. Instead, stream-rest on the result stream produces another stream that is like the one produced by (stream-lazy rest-expr).
The first element of the stream as produced by first-expr can be multiple values. The rest-expr must produce a stream when it is evaluated, otherwise the exn:fail:contract? exception is raised.
Changed in version 8.0.0.12 of package base: Added #:eager options.
Changed in version 8.8.0.7: Changed to allow multiple values.
syntax
(stream-lazy stream-expr)
(stream-lazy #:who who-expr stream-expr)
If evaluating stream-expr raises an exception or tries to force itself, then an exn:fail:contract exception is raised, and future attempts to force evaluation will trigger another exception.
If who-expr is provided, it is evaluated when constructing the delayed stream. If stream-expr later produces a value that is not a stream, and if who-expr produced a symbol value, then the symbol is used for the error message.
Added in version 8.0.0.12 of package base.
procedure
(stream-force s) → stream?
s : stream?
Normally, stream-force is not needed, because operations like stream-first, stream-rest, and stream-empty? force a delayed stream as needed. In rare cases, stream-force can be useful to reveal the underlying implementation of a stream (e.g., a stream that is an instance of a structure type that has the prop:stream property).
Added in version 8.0.0.12 of package base.
Changed in version 8.8.0.7 of package base: Changed to allow multiple values.
syntax
(stream* elem-expr ... tail-expr)
Added in version 6.3 of package base.
Changed in version 8.0.0.12: Changed to delay rest-expr even
if zero exprs are provided.
Changed in version 8.8.0.7: Changed to allow multiple values.
Changed in version 6.7.0.4 of package base: Improved element-reachability guarantee for streams in for.
value
procedure
(stream->list s) → list?
s : stream?
procedure
s : stream?
In the case of lazy streams, this function forces evaluation only of the sub-streams, and not the stream’s elements.
procedure
(stream-ref s i) → any
s : stream? i : exact-nonnegative-integer?
procedure
(stream-tail s i) → stream?
s : stream? i : exact-nonnegative-integer?
In case extracting elements from s involves a side effect, they will not be extracted until the first element is extracted from the resulting stream.
procedure
(stream-take s i) → stream?
s : stream? i : exact-nonnegative-integer?
procedure
(stream-append s ...) → stream?
s : stream?
procedure
(stream-map f s) → stream?
f : procedure? s : stream?
procedure
f : procedure? s : stream?
procedure
(stream-add-between s e) → stream?
s : stream? e : any/c
syntax
(for/stream (for-clause ...) body-or-break ... body)
syntax
(for*/stream (for-clause ...) body-or-break ... body)
Unlike most for forms, these forms are evaluated lazily, so each body will not be evaluated until the resulting stream is forced. This allows for/stream and for*/stream to iterate over infinite sequences, unlike their finite counterparts.
> (for/stream ([i '(1 2 3)]) (* i i)) #<stream>
> (stream->list (for/stream ([i '(1 2 3)]) (* i i))) '(1 4 9)
> (stream-ref (for/stream ([i '(1 2 3)]) (displayln i) (* i i)) 1) 2
4
> (stream-ref (for/stream ([i (in-naturals)]) (* i i)) 25) 625
> (stream-ref (for/stream ([i (in-naturals)]) (values i (add1 i))) 10)
10
11
Added in version 6.3.0.9 of package base.
Changed in version 8.8.0.7: Changed to allow multiple values.
value
To supply method implementations, the #:methods keyword should be used in a structure type definition. The following three methods must be implemented:
stream-empty? : accepts one argument
stream-first : accepts one argument
stream-rest : accepts one argument
> (struct list-stream (v) #:methods gen:stream [(define (stream-empty? stream) (empty? (list-stream-v stream))) (define (stream-first stream) (first (list-stream-v stream))) (define (stream-rest stream) (list-stream (rest (list-stream-v stream))))]) > (define l1 (list-stream '(1 2))) > (stream? l1) #t
> (stream-first l1) 1
Changed in version 8.7.0.5 of package base: Added a check so that omitting any of stream-empty?, stream-first, and stream-rest is now a syntax error.
value
If the c argument is a flat contract or a chaperone contract, then the result will be a chaperone contract. Otherwise, the result will be an impersonator contract.
When an stream/c contract is applied to a stream, the result is not eq? to the input. The result will be either a chaperone or impersonator of the input depending on the type of contract.
Contracts on streams are evaluated lazily by necessity (since streams may be infinite). Contract violations will not be raised until the value in violation is retrieved from the stream. As an exception to this rule, streams that are lists are checked immediately, as if c had been used with listof.
If a contract is applied to a stream, and that stream is subsequently used as the tail of another stream (as the second parameter to stream-cons), the new elements will not be checked with the contract, but the tail’s elements will still be enforced.
Added in version 6.1.1.8 of package base.