允许这样的突变是极好的。它允许您定义具有内部状态的对象,只能通过预先安排的方式访问:
(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
x
除了通过f
函数及其已建立的协议之外,没有办法改变它——正是因为 Scheme 中的词法作用域。
该x
变量指的是内部环境框架中的内存单元,属于let
定义内部的环境lambda
- 因此返回组合lambda
及其定义环境,也称为“闭包”。
如果你不提供改变这个内部变量的协议,没有什么可以改变它,因为它是内部的,我们早就离开了定义范围:
(set! x 5) ; WRONG: "x", what "x"? it's inaccessible!
编辑:您的新代码完全改变了您问题的含义,那里也没有问题。就像我们仍然在那个定义环境中一样,所以内部变量自然仍然可以访问。
比较有问题的是以下
(define x 1)
(define (f y) (+ x y))
(define x 4)
(f 5) ;?? it's 9.
我希望第二个定义不会干扰第一个,但R5RS 说define
就像set!
在顶层一样。
闭包将它们的定义环境与它们打包在一起。顶级环境始终是可访问的。
x
引用的变量f
位于顶级环境中,因此可以从同一范围内的任何代码访问。也就是说,任何代码。