[plt-scheme] streams

From: Nicholas Chubrich (chubrich at cs.brandeis.edu)
Date: Wed Mar 15 15:16:09 EST 2006

	You've forgotten that delay has to be a special form---see SICP 
pages 321 and 323.  Delay is syntactic sugar and would have to be defined 
with a macro.  Luckily, it's already present in MzScheme.
	Suppose you entered the following boneheaded but entirely legal 
program into DrScheme:

(define (delay obj) (lambda () obj))
;which is what you defined in your example program

(define (loop x) 
  (loop x))

and then called (delay (loop 2)).  But recall that calling a procedure
evaluates the arguments; the interpreter has to evaluate (loop 2) and
gets stuck.  The fact that (lambda () obj) is in the body of delay makes
not a whit of difference; the interpreter never actually gets there.
	On the other hand, if you write (lambda () (loop 2)), or even
(define proc (lambda () (loop 2))), you get a procedure---lambda simply
packages up its body into a procedure to be used when it is called. (loop
2) will only be evaluated when and if proc is called.  
	To elaborate slightly: at procedure definition time, all the
interpreter does with the body is make sure there are no syntax errors.  
Thus, if you try to evaluate (define (dumb x) (let x)), you get an error,
because let is a syntactic keyword.  On the other hand, you can put down
(define (dumb x) (cons x)) without so much as a peep; you only get in
trouble if you try to write say (dumb 2).
	Lazy evaluation simply means: do not evaluate arguments when a
procedure is called, wait until the value of the argument is actually
needed somewhere down the line.  See the rest of SICP for this.  The point
is you can't change the behavior of the interpreter simply by defining a
function.  You may be better off just using (lambda () obj) in place of
delay---lambda basically \is delay along with the ability to specify

Hope this helps and good luck.

Nick Chubrich.

> Hello,
> The following code is taken from SICP's section on
> streams verbatim.  While I realize there is an
> infinite recursion generating a stream of numbers,
> apparently the authors felt the code would work but
> drscheme seems to evaluate each infinite stream first.
>  Does this have something to do with lazy evaluation
> (a term I know nothing about?).  Is there some
> underlying reason for this that I don't know about or
> have I made some mistake with the code.
> Thanks in advance for your time...
> Dan Anderson
> (define (stream-car stream) (car stream))
> (define (stream-cdr stream) (force (cdr stream)))
> (define stream-null? null?)
> (define the-empty-stream '())
> (define (memo-proc proc)
>   (let ((already-run? false) (result false))
>     (lambda ()
>       (if (not already-run?)
>           (begin (set! result (proc))
>                  (set! already-run? true)
>                  result)
>           result))))
> (define (delay object) (memo-proc (lambda() object)))
> (define (cons-stream a b)
>   (cons a (delay b)))
> (define (force delayed-object)
>   (delayed-object))
> (define (stream-ref s n)
>   (if (= n 0)
>       (stream-car s)
>       (stream-ref (stream-cdr s) (- n 1))))
> (define (stream-map proc s)
>   (if (stream-null? s)
>       the-empty-stream
>       (cons-stream (proc (stream-car s))
>                    (stream-map proc (stream-cdr s)))))
> (define (stream-for-each proc s)
>   (if (stream-null? s)
>       'done
>       (begin (proc (stream-car s))
>              (stream-for-each proc (stream-cdr s)))))
> (define (display-stream s)
>   (stream-for-each display-line s))
> (define (display-line x)
>   (newline)
>   (display x))
> (define (stream-enumerate-interval low high)
>   (if (> low high)
>       the-empty-stream
>       (cons-stream
>        low
>        (stream-enumerate-interval (+ low 1) high))))
> (define (stream-filter pred stream)
>   (cond ((stream-null? stream) the-empty-stream)
>         ((pred (stream-car stream))
>          (cons-stream (stream-car stream)
>                       (stream-filter pred
>                                      (stream-cdr
> stream))))
>         (else (stream-filter pred (stream-cdr
> stream)))))
> (define (integers-starting-from n)
>   (cons-stream n (integers-starting-from (+ n 1))))
> ;
> (define integers (integers-starting-from 1))
> ;
> (define (divisible? x y) (= (remainder x y) 0))
> ;
> (define no-sevens
>   (stream-filter (lambda (x) (not (divisible? x 7)))
>                  integers))
> (define (sieve stream)
>   (cons-stream
>    (stream-car stream)
>    (sieve (stream-filter
>            (lambda (x)
>              (not (divisible? x (stream-car stream))))
>            (stream-cdr stream)))))
> (stream-ref no-sevens 100)

Posted on the users mailing list.