stream-define Richard Kelsey (12 Feb 2003 02:06 UTC)
|
Re: stream-define
bear
(12 Feb 2003 05:34 UTC)
|
Re: stream-define
bear
(12 Feb 2003 16:07 UTC)
|
stream-define Richard Kelsey 12 Feb 2003 02:05 UTC
I think you should replace STREAM-DEFINE with a non-DEFINE version. In introducing STREAM-DEFINE the SRFI says: ... with the (delay (force ...)) hidden within stream-define, which is the syntax used to create a function that returns a stream: The problem is that STREAM-DEFINE is syntax used to define a function that returns a stream, not just to create such a function. What about the LAMBDA's that are not the value in a DEFINE? Not to mention those benighted individuals who don't like the (DEFINE (F ...) ...) syntax in the first place. You could replace STREAM-DEFINE with STREAM-DELAY: (define-syntax stream-delay (syntax-rules () ((stream-delay x) (make-stream (delay (force (stream-promise x))))))) Then (stream-define (foo a b) stuff) could be written as (define (foo a b) (stream-delay stuff)) which has the advantage of making it possible to control which expressions get delayed and which don't. But mostly, it makes it clearer what is going on. Unless I am missing something the code in the SRFI uses STREAM-DEFINE more often than necessary. Take MAP2 and COUNTDOWN2 from the initial explanation of even and odd streams: (define (map2 func strm) (delay (force (if (nil2? strm) nil2 (cons2 (func (car1 strm)) (map2 func (cdr2 strm))))))) (define (countdown2 n) (delay (force (cons2 n (countdown2 (- n 1)))))) The DELAY-FORCE in MAP2 is needed to delay the call to NIL2?. Without it MAP2 wouldn't return a fully-lazy stream. But the DELAY-FORCE in COUNTDOWN2 is only delaying a CONS2 expression, which expands into a DELAY. There is no utility in delaying the creation of a delay. The reference implementation itself uses STREAM-DEFINE in many places where DEFINE would work, including the definitions of STREAM-FROM, STREAM-FROM-TO, STREAM-REPEAT, and STREAM-ITERATE. Many of the functions that do need a delay would benefit from moving the delay after some initial error checks. For example, writing STREAM-UNIQ using STREAM-DELAY allows it to signal errors when it is called instead of waiting until the result is forced: (define (stream-uniq eql? strm) (if (not (procedure? eql?)) (stream-error "non-functional argument to uniq")) (if (not (stream? strm)) (stream-error "non-stream argument to uniq")) (stream-delay (if (stream-null? strm) stream-null (let ((first (stream-car strm))) (stream-cons first (stream-uniq-aux eql? strm first))))) -Richard Kelsey