sicp stream-map 函数(3-50,3-51,3-52答案)

;;; stream-map 扫描流执行proc, 允许带多个流(每个流的元素个数应该相等)

(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 的流

(define (stream-enumerate-interval 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

(define y (stream-filter even? seq))

sum

1 ]=>
;Value: 6     ----- 定义y之后 sum的值为6,  sum的序列(1 3 6 ....),  是even?中的第一个偶数

(define z (stream-filter (lambda (x) (= (remainder x 5) 0))
             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的值每次都是变化的,具体为什么数与求值顺序相关。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值