SICP 全笔记

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