先载入所需的过程:
1 ]=> (load "p222-display-stream.scm")
;Loading "p222-display-stream.scm"... done
;Value: display-line
1 ]=> (load "p223-stream-enumerate-interval.scm")
;Loading "p223-stream-enumerate-interval.scm"... done
;Value: stream-enumerate-interval
定义 sum
和 accum
:
1 ]=> (define sum 0)
;Value: sum
1 ]=> (define (accum x)
(set! sum (+ x sum))
sum)
;Value: accum
从 sum
的值可以看出,在定义 seq
的时候,只有 1
被求值了:
1 ]=> (define seq (stream-map accum (stream-enumerate-interval 1 20)))
;Value: seq
1 ]=> sum
;Value: 1
从 sum
的值可以看出,在定义 y
的时候, seq
的求值进行到了 3
就停止了,因为 3
是 stream-filter
遇到的第一个非偶数值,其中 sum = 1 + 2 + 3 = 6
:
1 ]=> (define y (stream-filter even? seq))
;Value: y
1 ]=> sum
;Value: 6
从 sum
的值可以看出,在定义 z
的时候, seq
的求值进行到 4
就停止了,这时 sum = 1 + 2 + 3 + 4 = 10
:
1 ]=> (define z (stream-filter (lambda (x)
(= (remainder x 5) 0))
seq))
;Value: z
1 ]=> sum
;Value: 10
调用 (stream-ref y 7)
会让 y
被强迫求值,一直到第七个元素为止,这时 sum
也被设为了 (stream-ref y 7)
的值:
1 ]=> (stream-ref y 7)
;Value: 136
1 ]=> sum
;Value: 136
使用 display-stream
会强迫整个流求值:
1 ]=> (display-stream z)
10
15
45
55
105
120
190
210
;Unspecified return value
1 ]=> sum
;Value: 210
最后的问题是,如果将 (delay <exp)
的实现从 memo-proc
改为 (lambda () <exp>)
,会发生什么变化?
答案是,如果不使用记忆过程的话,那么对 seq
流的求值就会产生重复计算,而每次重复对 seq
的流的求值,都会引起 accum
过程的调用,结果会产生一个很不相同的 sum
值。
举个例子,即使再次调用 (display-stream z)
,这里的 sum
值也不会改变,但如果是没有使用记忆过程的 delay
实现,那么 sum
的值将会变成 420
:
1 ]=> (display-stream z)
10
15
45
55
105
120
190
210
;Unspecified return value
1 ]=> sum
;Value: 210