(stream-cons (1) stream-null) => stream David Van Horn (10 Nov 2006 23:38 UTC)
Re: (stream-cons (1) stream-null) => stream David Van Horn (10 Nov 2006 23:46 UTC)
Re: (stream-cons (1) stream-null) => stream AndrevanTonder (11 Nov 2006 00:41 UTC)
Re: (stream-cons (1) stream-null) => stream David Van Horn (11 Nov 2006 01:03 UTC)
Re: (stream-cons (1) stream-null) => stream AndrevanTonder (11 Nov 2006 12:32 UTC)
Re: (stream-cons (1) stream-null) => stream David Van Horn (11 Nov 2006 02:21 UTC)
Re: (stream-cons (1) stream-null) => stream AndrevanTonder (11 Nov 2006 14:19 UTC)

(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