考虑以下代码:
(define f2!
(let([n 0])
(lambda()
(set! n (add1 n))
n)))
(f2!)
(f2!)
我希望输出为1 1
,因为每次我们调用f2!
时,n
将重新定义为0。
但是输出为:1 2
。为什么会这样?
答案 0 :(得分:2)
您已完成一个针对变量关闭的函数。简而言之,这是一个可怜的人。
调用f1!
时,相同的自由绑定n
(实例变量)将被突变并返回。您已经创建了一个计数器。
您可以使用多种语言进行相同的操作,因为它们中的大多数都是词汇性的。例如。 JS:
const fBang = (() => {
let n = 0;
return () => ++n;
})();
console.log(fBang()); // prints 1
console.log(fBang()); // prints 2
答案 1 :(得分:1)
let
是所应用的lambda的语法糖,因此使用let的扩展形式可能更容易查看其原因:
(define f2!
((lambda (n)
(lambda () (set! n (add1 n)) n))
0))
因此,当您定义f2!
时,您应用 lambda(第二行),同时将其参数n
绑定到方案对象0
(第四行)。 f2!
的定义是该应用程序的另一个lambda对象的结果。
该内部Lambda具有一个环境,其中包含第一个Lambda(即n
)的参数。不是这些参数的副本,而是它们的实际引用,因此,当您应用内部lambda和set!
的值n
时,您将设置引用的n
的值就像您首次定义f2!
时所绑定的。
TL; DR,您一次定义了f2!
,然后绑定了n
,从那时起,您就获得并设置了相同的n
。