(stream-cons (1) stream-null) => stream
David Van Horn 10 Nov 2006 23:38 UTC
There is a serious bug in the reference implementation of SRFI 40, which
can be demonstrated by the following expression:
(stream-cons (1) stream-null)
According to the specification, this should evaluate to a stream. The
reference implementation, however, will evaluate (1), which is an error.
The following results are all calculated incorrectly by the reference
implementation (I've written what the expression should evaluate to,
according to the specification):
(stream-cons (1) stream-null) ;=> stream
(stream-null? (stream-cons (1) stream-null)) ;=> #f
(stream-pair? (stream-cons (1) stream-null)) ;=> #t
(stream-cdr (stream-cons (1) stream-null)) ;=> stream
(stream-null? (stream-cdr (stream-cons (1) stream-null)))
;=> #t
(stream-cons #t #f) ;=> error
I believe the following definitions of STREAM-CONS and STREAM-CAR will
fix the problem; it gives correct results for the above examples:
;; STREAM-CONS object stream -- primitive constructor of streams
(define-syntax stream-cons
(syntax-rules ()
((stream-cons obj strm)
(srfi-40:eager
(if (not (stream? strm))
(stream-error "attempt to stream-cons onto non-stream")
(cons (delay obj) strm))))))
;; STREAM-CAR stream -- first element of stream
(define (stream-car strm)
(cond ((not (stream? strm))
(stream-error "attempt to take stream-car of non-stream"))
((stream-null? strm)
(stream-error "attempt to take stream-car of null stream"))
(else (force (car (srfi-40:force (stream-promise strm)))))))
Currently, these are given as:
;; STREAM-CONS object stream -- primitive constructor of streams
(define-syntax stream-cons
(syntax-rules ()
((stream-cons obj strm)
(make-stream
(srfi-40:delay
(if (not (stream? strm))
(stream-error "attempt to stream-cons onto non-stream")
(cons obj strm)))))))
;; STREAM-CAR stream -- first element of stream
(define (stream-car strm)
(cond ((not (stream? strm))
(stream-error "attempt to take stream-car of non-stream"))
((stream-null? strm)
(stream-error "attempt to take stream-car of null stream"))
(else (car (srfi-40:force (stream-promise strm))))))
Before patching the reference implementation, I'd appreciate any reviews
or comments on this change. I know there are subtle space issues, which
I may have overlooked.
It's remarkable to me that this issue has not come up before.
David