Scheme 函数调用两次时,let中定义的变量发生更改
考虑以下代码:Scheme 函数调用两次时,let中定义的变量发生更改,scheme,racket,Scheme,Racket,考虑以下代码: (define f2! (let([n 0]) (lambda() (set! n (add1 n)) n))) (f2!) (f2!) 我希望输出是11,因为每次我们调用f2,n将被重新定义为0 但是输出是:12。这是为什么?您创建了一个在变量上闭合的函数。简言之,这是一个可怜的男人 当您调用f1相同的自由绑定n(实例变量)将被变异并返回。您已经创建了一个计数器 在许多语言中也可以这样做,因为大多数语言都是词汇性的。例如,JS: cons
(define f2!
(let([n 0])
(lambda()
(set! n (add1 n))
n)))
(f2!)
(f2!)
我希望输出是11
,因为每次我们调用f2代码>,n
将被重新定义为0
但是输出是:12
。这是为什么?您创建了一个在变量上闭合的函数。简言之,这是一个可怜的男人
当您调用f1
相同的自由绑定n
(实例变量)将被变异并返回。您已经创建了一个计数器
在许多语言中也可以这样做,因为大多数语言都是词汇性的。例如,JS:
const fBang=(()=>{
设n=0;
返回()=>++n;
})();
console.log(fBang());//印刷品1
console.log(fBang());//prints 2
let
是应用lambda的语法糖,因此使用let的扩展形式可能更容易理解其原因:
(定义f2!
((λ(n)
(lambda()(set!n(add1 n))n)
0))
所以当你定义f2代码>,在将其参数n
绑定到scheme对象0
(第4行)时应用lambda(第2行)。f2的定义代码>是该应用程序的结果,另一个lambda对象。
该内部lambda具有包含第一个lambda的参数的环境(即n
)。不是这些参数的副本,而是对它们的实际引用,所以当您应用内部lambda和集时代码>引用的n
的值,您正在将引用的n
的值设置为第一次定义f2时绑定的值代码>
TL;博士,你定义了f2
一次,在这一点上你绑定了n
,从那一点开始你得到并设置了相同的n
我认为n
绑定在闭包的局部范围内,但我对scheme不太熟悉:d您能再详细说明一下吗:dddd您返回一个使用副作用来更改n
的thr值的闭包。除了绑定到闭包范围的一次之外,它没有初始化。这并不是一个真正的答案,但出于您自己的启发,我建议您思考以下问题:为什么您认为n
每次都会被重新定义为0
f2代码>被调用?@AlexGoft太糟糕了,你删除了,这是一个有效的问题。ansewr是:grep'/'*|sed's/:.*/'|uniq-c