0

在“The Seasoned Schemer”的第 16 章中,作者定义了一个递归过程“depth”,它返回嵌套在 n 个列表中的 'pizza,例如 (depth 3) is ((((pizza)))。然后他们将其改进为“depthM”,它使用 set 缓存其返回值!在列表 Ns 和 Rs 中,它们一起形成了一个查找表,因此如果您达到以前见过的返回值,则不必一直向下递归。例如,如果我已经计算过 (depthM 8),当我稍后计算 (depthM 9) 时,我只需查找 (depthM 8) 的返回值并将其设置为 null,而不是一直递归到 (depthM 0) .

但随后他们将 Ns 和 Rs 移动到过程中,并用“let”将它们初始化为 null。为什么这不能完全破坏缓存返回值的意义?从一些实验来看,Ns 和 Rs 似乎在每次调用“depthM”时都被重新初始化。

我误解了他们的观点吗?

我想我的问题确实是这样的:Scheme 中有没有办法让词法范围的变量在调用过程之间保留它们的值,就像你可以在 Perl 5.10 中使用“状态”变量一样?

4

1 回答 1

5

呃。没有阅读经验丰富的计划者,我无法评论记忆问题,除非你在这里提供一些源代码。但是,关于是否有办法让词法范围的变量在函数调用之间保持状态的问题......这是Scheme语言的一个特性,称为“闭包”。考虑以下示例:

(define counter 
  (let ((number 0))
    (lambda () 
      (let ((result number))
        (set! number (+ number 1))
        result)))

这段代码定义了一个叫做 counter 的函数,它使用一个词法变量 ( number) 来跟踪它的状态。每次调用该函数时,您都会得到一个不同的数字作为回报:

> (counter)
0
> (counter)
1

等等。这里重要的一点是,执行lambda表达式生成的函数“关闭”了封闭范围内的所有词法可见变量(在这种情况下仅number.)。这意味着,这些变量仍然是读取值或写入新值的有效位置值到。

于 2010-04-05T14:58:13.787 回答