【发布时间】:2020-06-09 09:38:41
【问题描述】:
我正在阅读 SICP,但难以理解为无限流提供的一个示例:
https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-24.html#%_sec_3.5.2
我们可以通过使用诸如 add-streams 之类的操作来操作流来做更多有趣的事情,这会产生两个给定流的元素总和:62
(define (add-streams s1 s2)
(stream-map + s1 s2))
现在我们可以如下定义整数:
(define integers (cons-stream 1 (add-streams ones integers)))
我显然可以理解 integers 定义背后的意图,但我正在努力在脑海中“模拟”这个流。先前的示例不是问题,因为状态的维护是明确的。比如这个例子:
(define (integers-starting-from n)
(cons-stream n (integers-starting-from (+ n 1))))
(define integers (integers-starting-from 1))
我对整数的这个定义没有问题。
书中描述了ones的定义:
(define ones (cons-stream 1 ones))
这很像递归过程的定义:ones 是一对 car 为 1 且其 cdr 是评估 one 的承诺。评估 cdr 再次给我们一个 1 和一个评估的承诺,等等。
也许这条线让我失望了。 Ones 很简单,因为在每个stream-cdr 上都会对过程进行评估,并提供一个新的“1”和下一个承诺。
当我尝试将此推理应用于integers 时,我很难理解为什么结果流不是“1 2 2 2 2 2 ...”,因为整数会不断重新评估并基本上重新开始1.
编辑
我没有详细说明我的问题中是否要假设记忆是疏忽的。 SICP确实提到了答案中提出的二次行为问题,并以记忆delay函数的形式提供了解决方案:
(define (memo-proc proc)
(let ((already-run? false) (result false))
(lambda ()
(if (not already-run?)
(begin (set! result (proc))
(set! already-run? true)
result)
result))))
然后定义延迟,以便 (delay) 等价于
(memo-proc (lambda () <exp>))
【问题讨论】:
-
如果您难以在脑海中模拟它,为什么不使用笔和纸(或其他电子设备)来评估它? SICP教你Scheme使用的评估模型,所以这应该可以机械地做。如果你做了这件事还是不明白,你可以指出你没有得到哪些步骤。
-
查看这个带有明确状态的替代streams implementation,看看它是否对你来说更清楚。有时(经常?)同时从两个不同的角度看待问题会有所帮助。
标签: stream scheme infinite sicp lazy-sequences