Add for/stream and for*/stream comprehensions to racket/stream
Closes #664
This commit is contained in:
parent
34cfe48355
commit
f52d43e600
|
@ -1030,6 +1030,26 @@ stream, but plain lists can be used as streams, and functions such as
|
|||
new stream is constructed lazily.
|
||||
}
|
||||
|
||||
@deftogether[(@defform[(for/stream (for-clause ...) body-or-break ... body)]
|
||||
@defform[(for*/stream (for-clause ...) body-or-break ... body)])]{
|
||||
Iterates like @racket[for/list] and @racket[for*/list], respectively, but the
|
||||
results are lazily collected into a @tech{stream} instead of a list.
|
||||
|
||||
Unlike most @racket[for] forms, these forms are evaluated lazily, so each
|
||||
@racket[body] will not be evaluated until the resulting stream is forced. This
|
||||
allows @racket[for/stream] and @racket[for*/stream] to iterate over infinite
|
||||
sequences, unlike their finite counterparts.
|
||||
|
||||
@examples[#:eval sequence-evaluator
|
||||
(for/stream ([i '(1 2 3)]) (* i i))
|
||||
(stream->list (for/stream ([i '(1 2 3)]) (* i i)))
|
||||
(stream-ref (for/stream ([i '(1 2 3)]) (displayln i) (* i i)) 1)
|
||||
(stream-ref (for/stream ([i (in-naturals)]) (* i i)) 25)
|
||||
]
|
||||
|
||||
@history[#:added "6.3.0.9"]
|
||||
}
|
||||
|
||||
@defthing[gen:stream any/c]{
|
||||
Associates three methods to a structure type to implement the
|
||||
@tech{generic interface} (see @secref["struct-generics"]) for
|
||||
|
|
|
@ -57,4 +57,9 @@
|
|||
(test '(1 3) stream->list (stream-filter odd? '(1 2 3)))
|
||||
(test '(1 a 2 a 3) stream->list (stream-add-between '(1 2 3) 'a))
|
||||
|
||||
(test 4 'for/stream (stream-ref (for/stream ([x '(1 2 3)]) (* x x)) 1))
|
||||
(test 6 'for*/stream (stream-ref (for*/stream ([x '(1 2 3)] [y '(1 2 3)]) (* x y)) 7))
|
||||
(test 1 'for/stream (stream-first (for*/stream ([x '(1 0)]) (/ x))))
|
||||
(test 625 'for/stream (stream-ref (for/stream ([x (in-naturals)]) (* x x)) 25))
|
||||
|
||||
(report-errs)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
racket/generic
|
||||
racket/contract/base
|
||||
racket/contract/combinator
|
||||
racket/generator
|
||||
(rename-in "private/for.rkt"
|
||||
[stream-ref stream-get-generics])
|
||||
"private/sequence.rkt"
|
||||
|
@ -42,7 +43,10 @@
|
|||
stream-add-between
|
||||
stream-count
|
||||
|
||||
stream/c)
|
||||
stream/c
|
||||
|
||||
for/stream
|
||||
for*/stream)
|
||||
|
||||
(define-syntax gen:stream
|
||||
(make-generic-info (quote-syntax gen:stream)
|
||||
|
@ -300,3 +304,23 @@
|
|||
(if (chaperone-contract? ctc)
|
||||
(chaperone-stream/c ctc)
|
||||
(impersonator-stream/c ctc)))
|
||||
|
||||
;; Stream comprehensions -----------------------------------------------------------------------------
|
||||
|
||||
(define-syntaxes (for/stream for*/stream)
|
||||
(let ()
|
||||
(define ((make-for/stream derived-stx) stx)
|
||||
(syntax-case stx ()
|
||||
[(_ clauses . body)
|
||||
(begin
|
||||
(when (null? (syntax->list #'body))
|
||||
(raise-syntax-error (syntax-e #'derived-stx)
|
||||
"missing body expression after sequence bindings"
|
||||
stx #'body))
|
||||
#`(sequence->stream
|
||||
(in-generator
|
||||
(#,derived-stx #,stx () clauses
|
||||
(yield (let () . body))
|
||||
(values)))))]))
|
||||
(values (make-for/stream #'for/fold/derived)
|
||||
(make-for/stream #'for*/fold/derived))))
|
||||
|
|
Loading…
Reference in New Issue
Block a user