add stream-take + docs (#2181)

This commit is contained in:
bruno cuconato 2018-08-28 03:19:18 +00:00 committed by Alex Knauth
parent 3825a133ad
commit f9e6a8b61b
3 changed files with 38 additions and 0 deletions

View File

@ -1122,6 +1122,11 @@ stream, but plain lists can be used as streams, and functions such as
the resulting stream. the resulting stream.
} }
@defproc[(stream-take [s stream?] [i exact-nonnegative-integer?])
stream?]{
Returns a list of the first @racket[i] elements of @racket[s].
}
@defproc[(stream-append [s stream?] ...) @defproc[(stream-append [s stream?] ...)
stream?]{ stream?]{
Returns a stream that contains all elements of each stream in the Returns a stream that contains all elements of each stream in the

View File

@ -47,6 +47,7 @@
(test 3 stream-length '(1 2 3)) (test 3 stream-length '(1 2 3))
(test 1 stream-ref '(1 2 3) 0) (test 1 stream-ref '(1 2 3) 0)
(test '(2 3) stream-tail '(1 2 3) 1) (test '(2 3) stream-tail '(1 2 3) 1)
(test '(1 2) stream->list (stream-take '(1 2 3) 2))
(test '(1 2 3 4 5) stream->list (stream-append '(1 2 3) '(4 5))) (test '(1 2 3 4 5) stream->list (stream-append '(1 2 3) '(4 5)))
(test '(1 2 3) stream->list (stream-map values '(1 2 3))) (test '(1 2 3) stream->list (stream-map values '(1 2 3)))
(test #f stream-andmap even? '(1 2 3)) (test #f stream-andmap even? '(1 2 3))
@ -67,4 +68,18 @@
(test '(0 1 2 3 4 5) stream->list (for/stream ([i (in-naturals)]) (test '(0 1 2 3 4 5) stream->list (for/stream ([i (in-naturals)])
(define ii (sqr i)) #:break (> ii 30) i)) (define ii (sqr i)) #:break (> ii 30) i))
;; stream-take works on infinite streams with lazy-delayed errors later
(test '(1 4/3 4/2 4/1) stream->list
(stream-take (let loop ([i 4])
(stream-cons (/ 4 i) (loop (sub1 i))))
4))
;; stream-take preserves laziness, doesn't evaluate elements too early
(define (guarded-second s)
(if (stream-ref s 0) (stream-ref s 1) #f))
(define (div a b)
(stream (not (zero? b)) (/ a b)))
(test #f guarded-second (stream-take (div 1 0) 2))
(test 3/4 guarded-second (stream-take (div 3 4) 2))
(err/rt-test (stream->list (stream-take (stream 1 2) 3)) exn:fail:contract? "stream-take")
(report-errs) (report-errs)

View File

@ -33,6 +33,7 @@
stream-length stream-length
stream-ref stream-ref
stream-tail stream-tail
stream-take
stream-append stream-append
stream-map stream-map
stream-andmap stream-andmap
@ -115,6 +116,23 @@
[else [else
(loop (sub1 n) (stream-rest s))]))) (loop (sub1 n) (stream-rest s))])))
(define (stream-take st i)
(unless (stream? st) (raise-argument-error 'stream-take "stream?" st))
(unless (exact-nonnegative-integer? i)
(raise-argument-error 'stream-take "exact-nonnegative-integer?" i))
(let loop ([n i] [s st])
(cond
[(zero? n) empty-stream]
[(stream-empty? s)
(raise-arguments-error 'stream-take
"stream ended before index"
"index" i
"stream" st)]
[else
(stream* (stream-first s) (loop (sub1 n) (stream-rest s)))])))
(define (stream-append . l) (define (stream-append . l)
(for ([s (in-list l)]) (for ([s (in-list l)])
(unless (stream? s) (raise-argument-error 'stream-append "stream?" s))) (unless (stream? s) (raise-argument-error 'stream-append "stream?" s)))