【问题标题】:How to test if dynamic scope have been implemented correctly in lisp?如何测试动态范围是否已在 lisp 中正确实现?
【发布时间】:2018-06-13 19:05:45
【问题描述】:

我有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 和函数调用是唯一可以观察动态范围的地方吗?

【问题讨论】:

  • @coredump 如果变量未绑定,则它取自执行 is 的范围,这是动态范围,所以我认为它仅适用于函数和 let。我在问是这样还是我需要做其他事情才能使 lisp 动态化?
  • “Lisp 是使用 S-Expressions 的语言家族” - 对于更广泛的 Lisp 家族中的语言来说,s-expression 既不是必要的,也不是充分的。参见 Logo、RLISP、Dylan 等。
  • Scheme 和一些 Lisp 可能在很多方面有所不同:例如变量和函数是否在不同的命名空间中。例如,Common Lisp 支持变量的动态绑定,但不支持函数。
  • 函数调用..((lambda (y) (print (foo 10))) 2),但这和let一样..
  • 您可能还想检查以下内容(假设y 不是全局2((let ((y 2)) (lambda () y))),不应该返回2。如果您有异常或其他非本地传输您想要检查绑定在它们存在时是否正常工作的控制权。

标签: lisp dynamic-scope


【解决方案1】:

我还需要做些什么来使 lisp 动态化吗?

foo 看到由y 设置的绑定这一事实是一个重要的测试用例,它让我们确信正在进行一些动态范围的复制。

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

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

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

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

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

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

在Scheme 中,(define ...) 表单不做任何这样的事情,如果你让它这样做,你就破坏了语言;如果您希望在保持与 Scheme 兼容的同时拥有类似 CL 的动态变量,则需要一些其他形式,例如 (define-dynamic y ...),它将标记符号 y 以进行动态绑定。

【讨论】:

  • 我的动态范围选项不是像 CL 中那样按变量而是按解释器,因此我可以从单个库中创建动态或词法语言。对于动态的,我创建了两个动态和词法范围。 let 具有词法范围,但函数调用对 unboud 变量具有动态绑定。
猜你喜欢
  • 1970-01-01
  • 2012-09-18
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
  • 2023-01-28
  • 2019-01-19
  • 2016-05-09
  • 1970-01-01
相关资源
最近更新 更多