lisp - 如何测试动态范围是否已在 lisp 中正确实现?

标签 lisp dynamic-scope

我有simple lisp implementation based on scheme in JavaScript .默认情况下它具有词法作用域,但我刚刚添加了动态作用域作为选项。我如何测试我是否已正确实现:

此代码打印 20 和 30:

(define (foo x) (* x y))

(define y 1)

(let ((y 2))
   (print (foo 10))
   (let ((y 3))
       (print (foo 10))))

所以值 y 是动态的,因为它会随着函数 foo 的变化而变化,我还需要做些什么来使 lisp 动态化吗?

let 和函数调用是唯一可以观察动态范围的地方吗?

最佳答案

is there something else that I need to do to make lisp dynamic or this is it?

foo 正在查看由 y 设置的绑定(bind)这一事实是一个重要的测试用例,它让我们相信某些动态范围界定的复制品正在进行中。

另一个重要的测试是表明动态绑定(bind)没有被词法闭包捕获

假设我们绑定(bind)了 y,然后调用一个类似于 foo 的函数,它不是仅仅打印一个基于 y 的计算,而是捕获一个其主体执行该操作的词法闭包。然后在我们绑定(bind) y 的范围之外,我们调用返回的闭包。该闭包不能再看到我们绑定(bind)的 y 的值。引用 y 的闭包主体必须始终在当前动态环境中看到 y 的值。

您可能认为这是理所当然的,但您会惊讶地发现动态范围的某些实现很容易出错。如果您有某种用于实现动态范围的动态环境指针,并且该指针以某种方式卷入了词法闭包,哎呀,您现在拥有了捕获动态环境的闭包。 (当然,这可以是一个特性:“动态闭包”)。动态变量的“被调用函数查看父绑定(bind)”方面在动态闭包下工作得很好;这是一个独立的问题。

作为旁注,如果您的 (define y 1) 正在创建一个动态变量,那么词法变量是如何定义的?如果你想在同一种方言中同时支持动态和词法范围,你必须有一种方法来指定哪些符号将服从动态绑定(bind),哪些将保持词法。

即因为你支持动态范围“作为一个选项”,你需要有一种方法让它与词法范围的默认选项共存,并对此进行测试(你没有破坏词法范围)。

Common Lisp 通过将实际符号标记为特殊符号来做到这一点,这是由 defvardefparameter 完成的。

在 Scheme 中,(define ...) 形式不会做任何这样的事情,如果你让它这样做,你就会破坏语言;如果你想在保持与 Scheme 兼容的同时拥有类似 CL 的动态变量,你需要一些其他形式,比如 (define-dynamic y ...) 它将标记符号 y 用于动态绑定(bind)。

关于lisp - 如何测试动态范围是否已在 lisp 中正确实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50844526/

相关文章:

lisp - 在 CLISP 中列出目录

list - 为什么 `(a) read as a list while ` (a b) 不是?

scope - 为什么 Common Lisp 中的闭包没有捕获封闭函数的参数?

lisp - Emacs 口齿不清 : why does this sexp cause an invalid-function error?

python - 获取对调用该函数的 namespace 的引用

r - R 中的动态范围问题

lisp - 在 lisp 中解析逗号分隔的字符串

lisp - <<错误打印对象>> lisp - matlisp

Clojure:超出 gc 开销限制、懒惰评估、pi 序列

raku - 如何测试动态变量是否存在?