Re: stream-define Phil Bewig 14 Feb 2003 14:55 UTC

On Tuesday, February 11, 2003 8:05 PM, Richard Kelsey [SMTP:xxxxxx@s48.org] wrote:
> [ discussion of eliminating stream-define in favor of
>   stream-delay, followed by discussion of eliminating
>   unnecessary stream-defines in the reference
>   implementation ]

I suppose your point is that the essence of a stream is
the delay/force mechanism, and my library offers no
easy access to just that mechanism by itself, only in
combination with lambda and variable binding.  Thus
your stream-delay provides just that access and nothing
else, and can be used alongside lambda and define in
scheme expressions, just like any other data type.  If I
understood that right, then it's fine with me to add
stream-delay, although I think I prefer the name
make-stream, for consistency with make-string and
make-vector, and because stream-delay emphasizes
the implementation mechanism rather than the data
type.  (This means I will have to change the definition
of the :stream data type and several functions that
use it.)

There is also an intermediate step between
make-stream and stream-define.  Stream-lambda
combines the delay/force stream mechanism with
function creation:

    (define-syntax stream-lambda
      (syntax-rules ()
        ((stream-lambda spec body0 body1 ...)
          (lambda spec
            (make-stream
              (delay (force
                (stream-promise
                  (let () body0 body1 ...)))))))))

I used "let ()" here, but this might be a case where
"begin" is more appropriate.  Comments?

I left stream-lambda out of the SRFI because my
original mental model of stream functions was that
they would normally be defined recursively ("a stream
is an object followed by a stream"), but with
higher-order functions like stream-map and syntax
like stream-of that's not necessarily true, and a method
to create stream-valued functions belongs in the SRFI.
Thus I propose make-stream for the core and both
stream-lambda and stream-define for the derived
library.

Does all this make sense?

As to your other point, I may well have used
stream-define more often than necessary in the
reference implementation.  I was responding to a
problem that shows up with this version of
stream-cons that was used in several preliminary
versions of the SRFI:

    (define-syntax old-stream-cons
      (syntax-rules ()
        ((old-stream-cons obj strm)
          (if (not (stream? strm))
             (stream-error "attempt to stream-cons onto non-stream object")
             (make-stream (delay (cons obj strm)))))))

Given that definition, an expression like

    (define ones (old-stream-cons 1 ones))

doesn't work, because the (stream? strm) unnecessarily
strictifies old-stream-cons.  Delaying the error checks with
stream-define prevents the problem.  Having said that, this
issue of premature strictification was my biggest hangup in
writing this SRFI, and I may have erred in going too far while
trying to prevent it.

Phil