Exercise 3.51. In order to take a closer look at delayed evaluation, we will use the following procedure, which simply returns its argument after printing it:
(define (show x)
(display-line x)
x)
What does the interpreter print in response to evaluating each expression in the following sequence?59
(define x (stream-map show (stream-enumerate-interval 0 10)))
(stream-ref x 5)
(stream-ref x 7)
如果所用的 scheme 解释器没有 cons-stream 这一个 **特殊过程** ,那么可以如下定义这个特殊过程:
(define-syntax cons-stream
(syntax-rules ()
((cons-stream a b)
(cons a (delay b)))))
逐步分析
对于表达式
(define x (stream-map show (stream-enumerate-interval 0 10)))
我们逐个分析。
(stream-enumerate-interval 0 10) 等价于 (cons-stream 0 (delay (stream-enumerate-interval (+ low 1) high)))。
在 (stream-map show (stream-enumerate-interval 0 10)) 的时候,map 只会把一个 stream 的 car 取出来,然后调用 show。最后把这个调用以及之后要执行的过程给保存起来,即:
(cons (show (stream-car s))
(delay (stream-map show (stream-cdr s))))
; where s is (cons-stream 0 (delay (stream-enumerate-interval (+ low 1) high)))
所以 x 为
(0 . #[promise])
stream-ref
当调用 (stream-ref s n) 的时候,stream-ref 将会去求 stream-cdr。迫使之前的 #[promise] 执行 n 次
所以 (stream-ref x 5) 将会让之前的 (delay (stream-map show (stream-cdr s))) 执行,并且执行 5 次,s 被不断地被 stream-cdr 调用。
将会打印
1
2
3
4
5
再执行 (stream-ref x 7) 的时候,如果 scheme 解释器对于 force 的定义已经包含了 memo-proc 优化(见课本),那么将会记录之前的计算结果,从 6 开始打印
6
7