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