所以这是关于方案变量绑定的问题。假设我有以下功能:
(define undefinedTest (lambda (y) (list x y)))
当在Guile-Scheme 2.0.3中运行时,这将警告x是未绑定的变量。如果我然后执行以下语句
> (let ((x 'something)) (undefinedTest 'else))
我会收到错误并选择调试它。但是,如果我执行以下语句:
> (define x 'something)
> (undefinedTest 'else)
我得到了预期的答案(别的)。为什么scheme在顶层定义时能够绑定x,而不是在let绑定时绑定x。这是因为当定义函数时它也被定义在顶层,因此当方案去搜索其最近的封闭环境时,let环境实际上并没有“封闭”,因为它仍然在“top-”开始搜索水平”?
答案 0 :(得分:5)
Scheme使用词法作用域,而不是动态作用域。因此x
undefinedTest
看到的x
是从该函数词汇可见的{{1}},在这种情况下,正如您已经指出的那样,它是顶级范围。
答案 1 :(得分:1)
当undefinedTest
被定义时,它包含了定义它的环境;鉴于它是在顶层定义的,它只会“看到”其形式参数y
和全局环境 - 并且此时全局环境不包含x
。这就是因为Scheme是词法范围的。
我测试了Racket中问题中的代码,第一行失败并显示错误:expand: unbound identifier in module in: x
- 这意味着它甚至不是Racket解释的有效定义。
相同的示例适用于具有动态作用域的语言,Scheme使用词法作用域(a.k.a.静态作用域)。
答案 2 :(得分:1)
词汇范围是Scheme的核心功能。使用词法作用域,您始终可以确定哪些绑定对函数可见,因为它们是在定义函数的位置可见的。相比之下,动态范围界定会产生令人难以预料并且同样难以调试的意外情况。