在“The Seasoned Schemer”的第16章中,作者定义了一个递归过程“depth”,它返回'嵌套在n个列表中的披萨,例如(深度3)是(((披萨)))。然后他们将其改进为“depthM”,使用set缓存其返回值!在列表Ns和Rs中,它们共同形成一个查找表,因此如果达到之前看到的返回值,则不必一直向下递减。例如。如果我已经计算过(depthM 8),当我稍后计算(depthM 9)时,我只查找(depthM 8)的返回值并将其缩小为null,而不是一直递归到(depthM 0)。
然后他们在程序中移动Ns和Rs,并用“let”将它们初始化为null。为什么这不能完全破坏缓存返回值的点?从一些实验来看,似乎Ns和Rs在每次调用“depthM”时都会重新初始化。
我误解了他们的观点吗?
我想我的问题是这样的:在Scheme中是否有一种方法可以让词法范围的变量在调用过程之间保留它们的值,就像在Perl 5.10中使用“状态”变量一样?
答案 0 :(得分:5)
咄。没有阅读经验丰富的Schemer,我不能评论memoization问题,除非你在这里给出一些源代码。但是,关于是否有一种方法来使词法范围的变量保持其状态在函数调用之间的问题......这是Scheme语言的一个特征,称为“闭包”。请考虑以下示例:
(define counter
(let ((number 0))
(lambda ()
(let ((result number))
(set! number (+ number 1))
result)))
这段代码定义了一个名为counter的函数,它使用词法变量(number
)来跟踪其状态。每次调用该函数时,您将得到一个不同的数字作为回报:
> (counter)
0
> (counter)
1
等等。这里重要的一点是,执行lambda
表达式生成的函数“关闭”来自封闭范围的所有词汇可见变量(在这种情况下只有number
。)这意味着,那些变量保持有效的位置来读取值或将新值写入。