lisp - 如何测试动态范围是否已在 lisp 中正确实现?
问题描述
我有基于 JavaScript 中方案的简单 lisp 实现。默认情况下它具有词法范围,但我刚刚添加了动态范围作为选项。我如何测试我是否正确实现了这一点:
此代码打印 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 和函数调用是唯一可以观察动态范围的地方吗?
解决方案
我还需要做些什么来使 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
动态绑定的符号。
推荐阅读
- javascript - `Fetch` API 被覆盖。如何访问原始功能?
- amazon-web-services - 将 git rep 从 GCP 迁移到 AWS
- leaflet - 是否可以通过单击按钮打开 l-market 弹出窗口
- spring-boot - 构造嵌套json的有效方法?
- android - Flutter:是否可以在不使用 requestLegacyExternalStorage 或 MANAGE_EXTERNAL_STORAGE 权限的情况下将图像保存到图库?
- javascript - 指示滚动的渐变元素
- agora.io - 如何在与 agora RTC WEB 视频聊天期间发送消息(呼叫反应)
- python - matplotlib 折线图的奇怪尾部
- c - 用泰勒级数计算 sin(x)
- django-urls - 路由符号的 Django url 路径迁移 (1.11->3.1) 警告