【发布时间】:2011-04-09 22:20:53
【问题描述】:
我在 Racket/DrScheme 中测试了以下代码:
(define (makem)
(define x 34)
(list (lambda () (set! x (+ x 1)) x)
(lambda () (set! x (+ x 1)) x))
)
(define f (car (makem)))
(define f2 (car (cdr (makem))))
> (f)
35
> (f2)
35 ; I thought this would give me 36
> (f)
36
> (f)
37
>
在函数调用中创建的每个 lambda 是否都会获得其范围内每个变量的副本?是不是像某种隐式的让?我希望 lambda 有某种指向它们创建的范围的指针,使它们能够访问堆栈变量,但这告诉我不然,因为 f 和 f2 似乎有不同的 x 副本。究竟会发生什么?
【问题讨论】:
-
你应该真的去阅读chapter 3 of SICP.我一直很困惑,直到我读到它,然后它让整个过程变得非常清楚。请特别参阅第 3.2.3 节,“作为本地状态存储库的框架”。 (简短的回答:是的,它有点像隐含的
let,它们有不同的x副本。) -
同样在 SICP 中,看看 applicative-order 与 normal-order。这将解释为什么列表中的两个函数都将 x 设置为 35。
-
@mquander:他们只有
x的不同副本,因为它们来自(makem)的不同副本。如果它们实际上是对(makem)的一次调用的两个元素,而不是一次调用的第一个元素和另一个调用的第二个元素,那么它们将具有x的相同副本。 -
@dfan:是的,没错。
标签: lambda scope scheme closures