为什么 Scheme 允许在闭包中对封闭环境进行变异? [英] Why does Scheme allow mutation to closed environment in a closure?

查看:31
本文介绍了为什么 Scheme 允许在闭包中对封闭环境进行变异?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下方案代码

(let ((x 1))
   (define (f y) (+ x y))
   (set! x 2)
   (f 3) )

计算结果为 5 而不是 4.考虑到 Scheme 促进静态作用域,这令人惊讶.允许后续突变影响闭包中封闭环境中的绑定似乎恢复到有点动态范围.允许的任何具体原因?

which evaluates to 5 instead of 4. It is surprising considering Scheme promotes static scoping. Allowing subsequent mutation to affect bindings in the closed environment in a closure seems to revert to kinda dynamic scoping. Any specific reason that it is allowed?

我意识到上面的代码不太明显可以揭示我所关心的问题.我在下面放了另一个代码片段:

I realized the code above is less obvious to reveal the problem I am concerned. I put another code fragment below:

(define x 1)

(define (f y) (+ x y))

(set! x 2)

(f 3)  ; evaluates to 5 instead of 4

推荐答案

允许这样的突变很好.它允许您定义具有内部状态的对象,只能通过预先安排的方式访问:

Allowing such mutation is excellent. It allows you to define objects with internal state, accessible only through pre-arranged means:

(define (adder n)
  (let ((x n))    
    (lambda (y)
      (cond ((pair? y) (set! x (car y)))
            (else (+ x y))))))

(define f (adder 1))
(f 5)                 ; 6
(f (list 10))
(f 5)                 ; 15

除了通过 f 函数及其已建立的协议之外,没有办法更改 x - 正是因为 Scheme 中的词法作用域.

There is no way to change that x except through the f function and its established protocols - precisely because of lexical scoping in Scheme.

x 变量指的是内部环境框架中属于那个let 其中内部lambda 已定义 - 因此返回 lambda 及其定义环境的组合,也称为闭包".

The x variable refers to a memory cell in the internal environment frame belonging to that let in which the internal lambda is defined - thus returning the combination of lambda and its defining environment, otherwise known as "closure".

如果你不提供改变这个内部变量的协议,没有什么可以改变它,因为它是内部,我们早就离开了定义范围:

And if you do not provide the protocols for mutating this internal variable, nothing can change it, as it is internal and we've long left the defining scope:

(set! x 5) ; WRONG: "x", what "x"? it's inaccessible!

<小时>

您的新代码完全改变了您的问题的含义,那里也没有问题.就像我们仍然在那个定义环境中一样,所以自然而然地仍然可以访问内部变量.


your new code, which changes the meaning of your question completely, there's no problem there as well. It is like we are still inside that defining environment, so naturally the internal variable is still accessible.

比较麻烦的是以下

(define x 1)
(define (f y) (+ x y))
(define x 4)
(f 5) ;?? it's 9.

我希望第二个定义不会干扰第一个,但是 R5RSdefine 就像顶级的 set! .

I would expect the second define to not interfere with the first, but R5RS says define is like set! in the top-level.

闭包将它们的定义环境打包在一起.顶级环境始终可访问.

Closures package their defining environments with them. Top-level environment is always accessible.

f 引用的变量 x 位于顶级环境中,因此可以从同一范围内的任何代码访问.也就是说,任何代码.

The variable x that f refers to, lives in the top-level environment, and hence is accessible from any code in the same scope. That is to say, any code.

这篇关于为什么 Scheme 允许在闭包中对封闭环境进行变异?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆