Stream 延迟评估期间的回忆录

Stream 延迟评估期间的回忆录,stream,scheme,memoization,sicp,delayed-execution,Stream,Scheme,Memoization,Sicp,Delayed Execution,本书介绍了一个记忆过程,如下所示: (define (memo-proc proc) (let ((already-run? false) (result false)) (lambda () (if (not already-run?) (begin (set! result (proc)) (set! already-run? true) result) resu

本书介绍了一个记忆过程,如下所示:

(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)
be
(memo proc(lambda())
。可以使用以下步骤强制延迟对象:

(define (force delayed-object)
  (delayed-object))
在给出这些定义的章节中,使用流进行计算。每个流是一对,有一个头部和一个延迟的尾部

然而,我不知道如果不使用查找表,或者不使用积累以前调用的其他类型的数据结构,如何实现记忆化

包含这些定义的章节如下

当我们用各种参数记录单个过程时,查找表将非常有用。然后,我们将参数作为键,将过程的结果作为值。在本例中,我们有空过程,因此不需要查找表。我们所需要的只是一组迄今为止已经创建的延迟对象。但是,这里使用闭包

根据上面
memo proc
的定义,每个延迟对象实际上是一个具有值
已运行?
结果的闭包,这两个值都初始化为
false
。但是,由于调用
proc
中的每个延迟对象都有自己的闭包,并且它们自己的本地
已经运行了?
结果
,因此修改它们不会改变调用树中的其他对象。因此,我感觉一个记忆值再也不会被任何其他程序读取了


所以我的问题是,我认为什么是错误的,或者什么是对一切工作原理的正确解释?

每个延迟对象在第一次被强制后存储自己的值;该值存储在
结果
变量中。它之所以有效,是因为
memo proc
proc
承诺(等待评估的无参数过程)和
结果
变量上创建了一个闭包

第一次强制对象后,将返回存储的
结果
,并且不再重新计算。因此,承诺本身就是价值

我不知道如果不使用查找表,或者不使用积累以前调用的其他类型的数据结构,如何实现记忆化

数据结构是围绕每个承诺创建的闭包,它在
result
变量中累积第一个调用的值,并为所有后续调用返回该值

因此,我感觉记忆值再也不会被任何其他过程读取了


是的,每次在promise对象上调用
force
时都会读取它。

谢谢。我知道闭包是围绕每个承诺创建的。但是每次调用
(memoize proc)
时,它不是从头创建一个新的lambda吗,其中
结果
为零?那么,在对同一个已记忆过程的内部调用中,是什么阻止了
result
的值变为nil呢?如果再次调用
(memo proc proc)
,您正在创建一个新值,显然这个值还不会被记忆。它是否是以前在其他地方创建的值并不重要-这是一个新值,SICP中定义的记忆在每个值级别上工作,它不是全局的-它不能是全局的,除非我们将语言限制为纯功能子集,否则,变异操作将对在程序的多个部分中重用的预先计算的值造成严重破坏。因此,延迟表达式的每个实例实际上都是对
(memo proc proc)
的调用,并创建一个新的
已运行?
变量。那么备忘录在哪里呢?不,每次创建新的延迟表达式时,都会调用
memo proc
。如果继续强制已创建的延迟表达式,则会得到已记忆的值。例如:如果您定义了一个名为
integers
的流,并且程序的所有其余部分都使用该流,那么在第一次从该流强制执行某个值之后,该值将不再计算,它只返回已记忆的值。当然,如果你创建了一个名为
integers2
的新流,那么它的所有值都需要重新计算和记忆,因为它是一个不同的对象,没有被记忆。如果你做过任何面向对象的编程,你可能会发现想
(memo proc)更容易
作为返回对象实例的构造函数。然后像使用普通函数一样使用closure对象的这个实例。