#| -*-Scheme-*-
-$Id: stream.scm,v 14.10 1998/03/31 20:04:18 cph Exp $
+$Id: stream.scm,v 14.11 1998/04/01 08:16:01 cph Exp $
Copyright (c) 1988-98 Massachusetts Institute of Technology
(define (stream . list)
(list->stream list))
-(define (stream-length stream)
- (let loop ((stream stream) (length 0))
- (if (stream-pair? stream)
- (loop (force (cdr stream)) (+ length 1))
- (begin
- (if (not (null? stream))
- (error:wrong-type-argument stream "stream" 'STREAM-LENGTH))
- length))))
+(define stream-length
+ (letrec
+ ((loop
+ (lambda (stream length)
+ (if (stream-pair? stream)
+ (loop (force (cdr stream)) (+ length 1))
+ (begin
+ (if (not (null? stream))
+ (error:illegal-stream-element stream 'STREAM-LENGTH 0))
+ length)))))
+ (lambda (stream)
+ (loop stream 0))))
(define (stream-ref stream index)
(let ((tail (stream-tail stream index)))
(error:bad-range-argument index 'STREAM-REF))
(car tail)))
-(define (stream-head stream index)
- (if (not (exact-nonnegative-integer? index))
- (error:wrong-type-argument index
- "exact nonnegative integer"
- 'STREAM-HEAD))
- (let loop ((stream stream) (index index))
- (if (= 0 index)
- '()
- (begin
- (if (not (stream-pair? stream))
- (error:bad-range-argument index 'STREAM-HEAD))
- (cons (car stream)
- (loop (force (cdr stream)) (- index 1)))))))
+(define stream-head
+ (letrec
+ ((loop
+ (lambda (stream index)
+ (if (= 0 index)
+ '()
+ (begin
+ (if (not (stream-pair? stream))
+ (error:bad-range-argument index 'STREAM-HEAD))
+ (cons (car stream)
+ (loop (force (cdr stream)) (- index 1))))))))
+ (lambda (stream index)
+ (if (not (exact-nonnegative-integer? index))
+ (error:wrong-type-argument index
+ "exact nonnegative integer"
+ 'STREAM-HEAD))
+ (loop stream index))))
-(define (stream-tail stream index)
- (if (not (exact-nonnegative-integer? index))
- (error:wrong-type-argument index
- "exact nonnegative integer"
- 'STREAM-TAIL))
- (let loop ((stream stream) (index index))
- (if (= 0 index)
- stream
- (begin
- (if (not (stream-pair? stream))
- (error:bad-range-argument index 'STREAM-TAIL))
- (loop (force (cdr stream)) (- index 1))))))
+(define stream-tail
+ (letrec
+ ((loop
+ (lambda (stream index)
+ (if (= 0 index)
+ stream
+ (begin
+ (if (not (stream-pair? stream))
+ (error:bad-range-argument index 'STREAM-TAIL))
+ (loop (force (cdr stream)) (- index 1)))))))
+ (lambda (stream index)
+ (if (not (exact-nonnegative-integer? index))
+ (error:wrong-type-argument index
+ "exact nonnegative integer"
+ 'STREAM-TAIL))
+ (loop stream index))))
\f
-(define (stream-map procedure stream . streams)
- (if (null? streams)
- (let ((stream-map-1
- (lambda (procedure stream)
- (let loop ((stream stream))
- (if (stream-pair? stream)
- (cons-stream (procedure (car stream))
- (loop (force (cdr stream))))
- (begin
- (if (not (null? stream))
- (error:wrong-type-argument stream
- "stream"
- 'STREAM-MAP))
- '()))))))
- ;; Kludge: accept arguments in old order.
- (if (or (null? procedure) (stream-pair? procedure))
- (stream-map-1 stream procedure)
- (stream-map-1 procedure stream)))
- (let n-loop ((streams (cons stream streams)))
- (let parse-cars ((streams streams) (cars '()) (cdrs '()))
- (cond ((null? streams)
- (cons (apply procedure (reverse! cars))
- (let ((cdrs (reverse! cdrs)))
- (delay (n-loop (map force cdrs))))))
- ((stream-pair? (car streams))
- (parse-cars (cdr streams)
- (cons (car (car streams)) cars)
- (cons (cdr (car streams)) cdrs)))
- (else
- (if (not (null? (car streams)))
- (error:wrong-type-argument (car streams)
- "stream"
- 'STREAM-MAP))
- '()))))))
+(define stream-map
+ (letrec
+ ((do-1
+ (lambda (procedure stream)
+ (if (stream-pair? stream)
+ (cons-stream (procedure (car stream))
+ (do-1 procedure (force (cdr stream))))
+ (begin
+ (if (not (null? stream))
+ (error:illegal-stream-element stream 'STREAM-MAP 1))
+ '()))))
+ (do-n
+ (lambda (procedure streams)
+ (call-with-values (lambda () (split-streams streams 'STREAM-MAP))
+ (lambda (cars cdrs)
+ (if (null? cars)
+ '()
+ (cons (apply procedure cars)
+ (delay (do-n procedure (map force cdrs))))))))))
+ (lambda (procedure stream . streams)
+ (if (null? streams)
+ ;; Kludge: accept arguments in old order.
+ (if (or (null? procedure) (stream-pair? procedure))
+ (do-1 stream procedure)
+ (do-1 procedure stream))
+ (do-n procedure (cons stream streams))))))
-(define (stream-for-each procedure stream . streams)
- (if (null? streams)
- (let loop ((stream stream))
- (cond ((stream-pair? stream)
- (procedure (car stream))
- (loop (force (cdr stream))))
- ((not (null? stream))
- (error:wrong-type-argument stream "stream" 'STREAM-FOR-EACH))))
- (let n-loop ((streams (cons stream streams)))
- (let parse-cars ((streams streams) (cars '()) (cdrs '()))
- (cond ((null? streams)
- (apply procedure (reverse! cars))
- (n-loop (map force (reverse! cdrs))))
- ((stream-pair? (car streams))
- (parse-cars (cdr streams)
- (cons (car (car streams)) cars)
- (cons (cdr (car streams)) cdrs)))
- ((not (null? (car streams)))
- (error:wrong-type-argument (car streams)
- "stream"
- 'STREAM-FOR-EACH)))))))
-\f
-(define (stream-append . streams)
- (if (null? streams)
- '()
- (let outer-loop ((streams streams))
- (if (null? (cdr streams))
- (car streams)
- (let inner-loop ((stream (car streams)))
- (if (stream-pair? stream)
- (cons-stream (car stream)
- (inner-loop (force (cdr stream))))
+(define stream-for-each
+ (letrec
+ ((do-1
+ (lambda (procedure stream)
+ (cond ((stream-pair? stream)
+ (procedure (car stream))
+ (do-1 procedure (force (cdr stream))))
+ ((not (null? stream))
+ (error:illegal-stream-element stream 'STREAM-FOR-EACH 1)))))
+ (do-n
+ (lambda (procedure streams)
+ (call-with-values
+ (lambda () (split-streams streams 'STREAM-FOR-EACH))
+ (lambda (cars cdrs)
+ (if (not (null? cars))
(begin
- (if (not (null? stream))
- (error:wrong-type-argument (car streams)
- "stream"
- 'STREAM-APPEND))
- (outer-loop (cdr streams)))))))))
+ (apply procedure cars)
+ (do-n procedure (map force cdrs)))))))))
+ (lambda (procedure stream . streams)
+ (if (null? streams)
+ (do-1 procedure stream)
+ (do-n procedure (cons stream streams))))))
+
+(define (split-streams streams operator)
+ (let ((cars (list 'CARS))
+ (cdrs (list 'CDRS)))
+ (let loop ((streams streams) (cars-tail cars) (cdrs-tail cdrs) (n 0))
+ (if (null? streams)
+ (values (cdr cars) (cdr cdrs))
+ (let ((stream (car streams)))
+ (if (stream-pair? stream)
+ (let ((cars-tail* (list (car stream)))
+ (cdrs-tail* (list (cdr stream))))
+ (set-cdr! cars-tail cars-tail*)
+ (set-cdr! cdrs-tail cdrs-tail*)
+ (loop (cdr streams) cars-tail* cdrs-tail* (fix:+ n 1)))
+ (begin
+ (if (not (null? stream))
+ (error:illegal-stream-element stream operator n))
+ (values '() '()))))))))
+\f
+(define stream-append
+ (letrec
+ ((outer-loop
+ (lambda (streams n)
+ (if (null? (cdr streams))
+ (car streams)
+ (inner-loop (car streams) (cdr streams) n))))
+ (inner-loop
+ (lambda (stream streams n)
+ (if (stream-pair? stream)
+ (cons-stream (car stream)
+ (inner-loop (force (cdr stream)) streams n))
+ (begin
+ (if (not (null? stream))
+ (error:illegal-stream-element stream 'STREAM-APPEND n))
+ (outer-loop streams (fix:+ n 1)))))))
+ (lambda streams
+ (if (null? streams)
+ '()
+ (outer-loop streams 0)))))
(define (stream-accumulate procedure initial stream)
- (let loop ((stream stream))
- (if (stream-pair? stream)
- (procedure (car stream)
- (loop (force (cdr stream))))
- (begin
- (if (not (null? stream))
- (error:wrong-type-argument stream "stream" 'STREAM-ACCUMULATE))
- initial))))
+ (if (stream-pair? stream)
+ (procedure (car stream)
+ (stream-accumulate procedure initial (force (cdr stream))))
+ (begin
+ (if (not (null? stream))
+ (error:illegal-stream-element stream 'STREAM-ACCUMULATE 2))
+ initial)))
(define (stream-filter predicate stream)
- (let loop ((stream stream))
- (if (stream-pair? stream)
- (if (predicate (car stream))
- (cons-stream (car stream) (loop (force (cdr stream))))
- (loop (force (cdr stream))))
- (begin
- (if (not (null? stream))
- (error:wrong-type-argument stream "stream" 'STREAM-FILTER))
- '()))))
+ (if (stream-pair? stream)
+ (if (predicate (car stream))
+ (cons-stream (car stream)
+ (stream-filter predicate (force (cdr stream))))
+ (stream-filter predicate (force (cdr stream))))
+ (begin
+ (if (not (null? stream))
+ (error:illegal-stream-element stream 'STREAM-FILTER 1))
+ '())))
-(define (stream-write stream #!optional port)
- (let ((port
- (if (default-object? port)
- (current-output-port)
- (guarantee-output-port port))))
- (let loop ((stream stream) (leader #\{))
- (if (stream-pair? stream)
- (begin
- (write-char leader port)
- (write (car stream) port)
- (loop (force (cdr stream)) #\space))
- (begin
- (if (not (null? stream))
- (error:wrong-type-argument stream "stream" 'STREAM-WRITE))
- (write-char #\} port))))))
+(define stream-write
+ (letrec
+ ((loop
+ (lambda (stream leader port)
+ (if (stream-pair? stream)
+ (begin
+ (write-char leader port)
+ (write (car stream) port)
+ (loop (force (cdr stream)) #\space port))
+ (begin
+ (if (not (null? stream))
+ (error:illegal-stream-element stream 'STREAM-WRITE 0))
+ (write-char #\} port))))))
+ (lambda (stream #!optional port)
+ (loop stream
+ #\{
+ (if (default-object? port)
+ (current-output-port)
+ (guarantee-output-port port))))))
(define (list->stream list)
(if (pair? list)
(stream->list (force (cdr stream))))
(begin
(if (not (null? stream))
- (error:wrong-type-argument stream "stream" 'STREAM->LIST))
+ (error:illegal-stream-element stream 'STREAM->LIST 0))
'())))
\f
(define prime-numbers-stream)
(define (make-prime-numbers-stream)
(cons-stream
2
- (letrec ((primes
- (cons-stream
- (cons 3 9)
- (let filter ((integer 5))
- (let loop ((primes primes))
- (let ((prime (car primes)))
- (cond ((< integer (cdr prime))
- (cons-stream (cons integer (* integer integer))
- (filter (+ integer 2))))
- ((= 0 (remainder integer (car prime)))
- (filter (+ integer 2)))
- (else
- (loop (force (cdr primes)))))))))))
+ (letrec
+ ((primes
+ (cons-stream
+ (cons 3 9)
+ (let filter ((integer 5))
+ (let loop ((primes primes))
+ (let ((prime (car primes)))
+ (cond ((< integer (cdr prime))
+ (cons-stream (cons integer (* integer integer))
+ (filter (+ integer 2))))
+ ((= 0 (remainder integer (car prime)))
+ (filter (+ integer 2)))
+ (else
+ (loop (force (cdr primes)))))))))))
(let loop ((primes primes))
(cons-stream (car (car primes))
(loop (force (cdr primes))))))))
(set! prime-numbers-stream (make-prime-numbers-stream))
unspecific)))
(reset-primes!)
- (add-secondary-gc-daemon! reset-primes!)))
\ No newline at end of file
+ (add-secondary-gc-daemon! reset-primes!)))
+
+(define (error:illegal-stream-element stream operator operand)
+ (error (make-illegal-stream-element "stream" stream operator operand)))
+
+(define make-illegal-stream-element)
+(define condition-type:illegal-stream-element)
+
+(define (initialize-conditions!)
+ (set! condition-type:illegal-stream-element
+ (make-condition-type 'ILLEGAL-STREAM-ELEMENT
+ condition-type:wrong-type-argument
+ '()
+ (lambda (condition port)
+ (write-string "The object " port)
+ (write (access-condition condition 'DATUM) port)
+ (write-string ", occurring in the " port)
+ (write-string (ordinal-number-string
+ (+ (access-condition condition 'OPERAND) 1))
+ port)
+ (write-string " argument to " port)
+ (write-operator (access-condition condition 'OPERATOR) port)
+ (write-string ", is not a stream." port))))
+ (set! make-illegal-stream-element
+ (condition-constructor condition-type:illegal-stream-element
+ '(TYPE DATUM OPERATOR OPERAND)))
+ unspecific)
\ No newline at end of file