【问题标题】:Memoization during delayed evaluation延迟评估期间的记忆
【发布时间】:2013-03-30 00:36:24
【问题描述】:

Structure and Interpretation of Computer Programs这本书介绍了一个memoizing过程如下:

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

(define (force delayed-object)
  (delayed-object))

在给出这些定义的章节中,计算是使用流完成的。每个流都是一对,有一个头和一个延迟的尾。

但是,如果不使用查找表或其他类型的累积先前调用的数据结构,我看不出如何实现记忆化。

包含这些定义的章节是here

当我们使用各种参数来记忆单个过程时,查找表会很有用。然后,我们将参数作为键,将过程的结果作为值。在这种情况下,我们有空程序,因此我们不需要查找表。我们所需要的只是我们迄今为止创建的一组延迟对象。但是,这里使用了闭包。

根据上面memo-proc的定义,每个延迟对象实际上都是一个闭包,其值为already-run?result,它们都被初始化为false。但是,由于调用 proc 中的每个延迟对象都有自己的闭包以及它们自己的本地 already-run?result,因此修改它们不会更改调用树中的其他对象。因此,我觉得任何其他程序都不会再读取一个记忆值。

所以我的问题是,我在想什么错误或者对一切如何运作的正确解释是什么?

【问题讨论】:

    标签: stream scheme memoization sicp delayed-execution


    【解决方案1】:

    每个延迟对象在第一次强制执行后都会存储自己的值;该值存储在result 变量中。它之所以有效,是因为 memo-procproc - promise(等待评估的无参数过程)和 result 变量上创建了一个闭包。

    第一次强制对象后,存储的result 被返回,并且不再重新计算。所以 promise 变成了 value 本身。

    如果不使用查找表或某种其他类型的累积先前调用的数据结构,我看不出如何实现记忆化。

    数据结构是围绕每个 Promise 创建的闭包,它将第一次调用的值累积到 result 变量中,并将其返回给所有后续调用。

    因此,我觉得任何其他程序都不会再读取一个记忆值

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

    【讨论】:

    • 谢谢。我知道闭包是围绕每个承诺创建的。但是每次调用(memoize proc) 时,它不是从头开始创建一个新的lambda,其中result 是nil 吗?那么,是什么阻止了result 在对同一个记忆过程的内部调用中为零?
    • 如果您再次调用(memo-proc proc),您正在创建一个新值,显然这还不会被记忆。如果它是之前在其他地方创建的值并不重要 - 这是一个 值,SICP 中定义的记忆化在每个值级别上工作,它不是全局的 - 它可以t 是,除非我们将语言限制为纯函数子集,否则变异操作将对在程序的多个部分中重用的预计算值造成严重破坏
    • 因此,延迟表达式的每个实例实际上都是对(memo-proc proc) 的调用,并创建了一个新的already-run? 变量。那么记忆在哪里呢?
    • 不,每次您创建一个新的延迟表达式时,您都调用memo-proc。如果您继续强制一个已经创建的延迟表达式,您将获得记忆值。例如:如果您定义了一个名为 integers 的流,并且您的程序的所有其余部分都使用该流,那么在第一次从流中强制一个值之后,它将不再被评估,它只会返回记忆化的值。当然,如果您创建一个名为 integers2 的新流,那么它的所有值都需要再次计算并再次记忆,因为它是一个尚未记忆的不同对象
    • 如果您做过任何面向对象的编程,您可能会发现将(memo-proc proc) 视为返回对象的实例 的构造函数更容易。然后像使用普通函数一样使用闭包对象的这个实例。
    猜你喜欢
    • 1970-01-01
    • 2021-05-17
    • 2012-11-16
    • 1970-01-01
    • 2011-03-03
    • 1970-01-01
    • 2016-06-20
    • 1970-01-01
    • 2014-10-18
    相关资源
    最近更新 更多