我还需要做些什么来使 lisp 动态化,或者就是这样?
foo
看到绑定设置的事实y
是一个重要的测试用例,它让我们相信一些动态范围的复制正在发生。
另一个重要的测试是表明动态绑定没有被词法闭包捕获。
假设我们 bind y
,然后调用一个类似的函数,foo
而不是仅仅打印一个基于y
捕获其主体的词法闭包的计算。然后在我们绑定的范围之外y
,我们称之为返回的闭包。该闭包必须不再看到y
我们绑定的值。引用的闭包主体必须始终在当前动态环境中y
看到 的值。y
您可能认为这是理所当然的,但您会惊讶于动态范围的某些实现很容易出错。如果您有某种用于实现动态范围的动态环境指针,并且该指针不知何故卷入了词法闭包中,哎呀,您现在有了捕获动态环境的闭包。(当然,这可以是一个特性:“动态闭包”)。动态变量的“调用函数查看父绑定”方面在动态闭包下工作得很好;这是一个独立的问题。
作为旁注,如果您(define y 1)
正在创建一个动态变量,那么词法变量是如何定义的?如果你想在同一个方言中同时支持动态和词法范围,你必须有一种方法来指定哪些符号将服从动态绑定,哪些将保持词法。
即,由于您“作为选项”支持动态范围,因此您需要有一种方法使其与词法范围的默认选项共存,并对此进行测试(您没有破坏词法范围)。
Common Lisp 通过将实际符号标记为特殊来做到这一点,这是由defvar
和完成的defparameter
。
在 Scheme 中,(define ...)
表单不做任何这样的事情,如果你让它这样做,你就破坏了语言;如果你想在保持与 Scheme 兼容的同时拥有类似 CL 的动态变量,你需要一些其他的形式来(define-dynamic y ...)
标记y
动态绑定的符号。