我发现检查范围是词汇还是动态的程序是下面给出的(来源:http://inst.eecs.berkeley.edu/~cs61a/su10/resources/sp11-Jordy/scope/)
(define test
(let ((scope 'lexical))
(lambda () scope)))
(let ((scope 'dynamic))
(test))
但这怎么可行呢?这应该始终打印'词汇(无论范围是词汇还是动态)对吗?因为在第一个'let'的主体的局部范围内,范围总是被定义为'词汇..如果我错了请纠正我
答案 0 :(得分:6)
Scheme使用词法作用域,因此代码总是返回lexical
。但是,在使用动态作用域的Lisp系统中,scope
在dynamic
表达式中确实是(let ((scope 'dynamic)) ...)
....
为了理解这一点,您必须了解动态范围的实现方式。将每个变量视为具有一堆值。†因此,在评估lambda表达式时,值lexical
已被推送到scope
' s值栈(通过let
)。退出let
块时,将弹出该值。之后,第二个let
块会将值dynamic
推送到scope
的值堆栈,这是您的函数所看到的。
†我非常感谢the explanation from the Emacs Lisp manual关于动态绑定如何在堆栈方面工作。它帮助我真正理解了这个概念。
答案 1 :(得分:6)
test
的值不是
(let ((scope 'lexical))
(lambda () scope))
只是
(lambda () scope)
当你调用(test)
时,会评估函数体,它只包含
scope
对于词法范围,这将是在评估定义时生效的绑定中的值,即词法封闭let
- 绑定。
对于动态范围,在调用函数之前不会查找scope
的绑定
那时,对'lexical
的绑定早已消失 - 它只存在于test
的定义中。
当你
(let ((scope 'dynamic))
(test))
在环境中引入了新绑定,这是查找scope
时找到的绑定。
类似的功能
(define test
(lambda ()
(let ((scope 'whatever))
scope)))
会按照您建议的方式运作 - 始终返回'whatever
- 因为'whatever
的绑定在评估scope
期间即使在动态设置中也有效。