【问题标题】:SICP 3.52 delayed cdrSICP 3.52 延迟 cdr
【发布时间】:2021-06-05 01:09:26
【问题描述】:

Exercise 3.52,

(define sum 0)

(define (accum x)
  (set! sum (+ x sum))
  sum)

;1: (define seq (stream-map accum (stream-enumerate-interval 1 20)))
;2: (define y (stream-filter even? seq))
;3: (define z (stream-filter (lambda (x) (= (remainder x 5) 0))
;                           seq))

;4: (stream-ref y 7)
;5: (display-stream z)

第 1 步: ;1: ==> (cons-stream 1 (stream-map proc (stream-cdr s))(假设 stream-cdr 仅在我们强制此流的 cdr 时评估)

sum 现在是 1

第 2 步: 1 不是甚至,因此(也被记住所以不再添加),它调用(stream-filter pred (stream-cdr stream))。 这将导致 评估cdr 从而实现2 ,因此它应该调用:(cons-stream 2 (stream-cdr stream))

根据这个答案应该是 1+2 = 3 ,但它是 6

有人可以帮助解释为什么 cdrcar 在当前的 cdr 被调用之前实现吗?

【问题讨论】:

    标签: stream scheme sicp lazy-sequences


    【解决方案1】:

    使用Daniel P. Friedman's memoizing tail

    #lang r5rs
    
    (define-syntax cons-stream
      (syntax-rules () 
        ((_ h t) (cons h (lambda () t)))))
    
    (define (stream-cdr s)
      (if (and (not (pair? (cdr s)))
               (not (null? (cdr s))))
          (set-cdr! s ((cdr s))))
      (cdr s))
    

    我们观察:

    > sum
    0
    > (define seq (stream-map accum (stream-enumerate-interval 1 20)))
    > sum
    1
    > seq
    (mcons 1 #<procedure:friedmans-tail.rkt:21:26>)
    > (define y (stream-filter even? seq))
    > sum
    6
    > seq
    (mcons
     1
     (mcons
      3
      (mcons 6 #<procedure:friedmans-tail.rkt:21:26>)))
    > y
    (mcons 6 #<procedure:friedmans-tail.rkt:21:26>)
    > 
    

    stream-filter? 需要到达它正在构造的流的第一个元素才能构造它。流的头部元素已经被强制计算,因此它必须已经存在。

    在1到20的枚举区间的累加和列表中,第一个偶数是6:

    1      = 1
    1+2    = 3
    1+2+3  = 6
    ...
    

    【讨论】:

    • 在 Racket 中运行。
    • 要查看更多信息,请同时命名枚举序列:(define nums (stream-enumerate-interval 1 20)) (define seq (stream-map accum nums)) 并检查 nums 以及 seq 等,同时逐个尝试表达式。
    猜你喜欢
    • 1970-01-01
    • 2011-07-23
    • 2011-08-02
    • 2017-07-28
    • 1970-01-01
    • 2019-06-07
    • 2015-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多