循环宏中的Common Lisp绑定

10

我想在循环中重新绑定一个特殊变量。通常情况下,可以使用 let 来实现这一点。

(let ((*read-eval* nil))
  (do-something-here))

但由于loop宏拥有这些不错的with子句,我认为我可能可以在其中实现。表达式(macroexpand '(loop with *read-eval* = nil))最终会将绑定展开为let,因此它肯定适用于我的实现。但我在标准文档中找不到任何指示这是标准化行为的内容。因此,我的问题是:

(loop with *read-eval* = nil
      for i from 1 to 10
      do (something-involving-the-read-function))

符合规范的实现是否需要修改现有的*read-eval*变量,还是存在它们可能创建一个同名的新词法变量的风险?

1个回答

8

*read-eval* 是一个全局特殊变量。无法撤销它,也就是说,无法为其创建本地词法绑定。

with 子句被描述为使用 绑定(而不仅是设置),这意味着,确实,一旦循环完成,我们将回到原始值(回答 @joshua-tailor 的问题)。

让我们理性思考。 (loop with foo = nil ...) 明显为 foo 建立了一个绑定。因此,对于 (loop with *read-eval* = nil ...) 而言,系统需要在宏展开或编译时检查 *read-eval* 是否会在运行时成为动态变量,才能不建立该绑定。这听起来很疯狂。


2
这是正确的,但仍然不清楚loop是否需要重新绑定,而不仅仅是分配。我们知道一旦循环完成,我们会回到原始值吗?我非常确定答案是肯定的,基于http://www.lispworks.com/documentation/HyperSpec/Body/06_abb.htm,它说变量在循环外部不存在。措辞对于特殊变量并不特别适用,但看起来唯一合理的解释是名称的局部绑定,这意味着*let*(或*lambda*等)。 - Joshua Taylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接