(define (stream-map proc . argstreams)
(if (stream-null? (car argstreams))
the-empty-stream
(cons-stream
(apply proc (map stream-car argstreams))
(apply stream-map (cons proc (map stream-cdr argstreams))))))
------------------------------------------------------------------------------------------------
;;;; 3-51 观察延时求值
;;; 生成 low 到 high 的流
(if (> low high)
the-empty-stream
(cons-stream
low
(stream-enumerate-interval (+ low 1) high))))
(define (show x)
(display x)
(newline)
x)
(define x (stream-map show (stream-enumerate-interval 0 10)))
1 ]=> 0
;Value: x
;;; 由输出结果可以看出stream-map 只调用了一次show, 其他的均延时求值
(stream-ref x 5)
1 ]=> 1
2
3
4
5
;Value: 5
;; 只show了 1 2 3 4 5, 没show 0, 因为定义x的时候0已经show过了
(stream-ref x 7)
1 ]=> 6
7
;Value: 7
;; 只show 6 7, 0-5在前面已经show过了
;;; 由以上显示结果可以看出,每个元素只被show一次,说明了delay是带记忆性求值。
;;; 注: (define (cons-stream a b) (cons a (delay b))
;;; ---------------- 3.52 -----------------------------------------
(define sum 0)
(define (accum x)
(set! sum (+ x sum))
sum))
(define seq (stream-map accum (stream-enumerate-interval 1 20)))
sum
1 ]=>
;Value: 1 ------ 定义 seq 之后 sum的值为 1
sum
1 ]=>
;Value: 6 ----- 定义y之后 sum的值为6, sum的序列(1 3 6 ....), 是even?中的第一个偶数
seq))
sum
1 ]=>
;Value: 10 ----- 定义z之后 sum的值为10, sum的序列为(1 3 6 10 ...), 10是5的第一个倍数
(stream-ref y 7)
1 ]=>
;Value: 136 ----- y的第7个值为 136
sum
1 ]=>
;Value: 136 ------- sum的值为 136, 说明y的求值会驱动sum的求值
(display-stream z)
1 ]=> 10
15
45
55
105
120
190
210 ---- 打印出所有的z元素, 最大值为210
sum
1 ]=>
;Value: 210 ---- sum的值为210, 说明z的求值会驱动sum的求值
总结: y和z这两个流是基于 seq 这个流来过滤的, 所以y、z的求值会迫使seq去求值
如果(delay exp) 实现为 (lambda () exp)的话,会导致流的重复求值,即 seq的重复求值导致sum的值每次都是变化的,具体为什么数与求值顺序相关。