6

我正在阅读Gigamonkey (Peter Seibel's) 的 Practical Common Lisp ,并在宏章节中关于 DO 的部分中遇到了以下声明:

与 LET 中的变量定义一样,如果省略了 init 形式,则该变量将绑定到 NIL。同样与 LET 一样,您可以使用普通变量名称作为仅包含名称的列表的简写。

我不知道他所说的“使用普通变量作为仅包含名称的列表的缩写”,即第二句话是什么意思。第一句在LET 的 Common-Lisp Hyperspec 中得到了支持,并通过一个简单的例子来支持(let (n) n) ~~> NIL,但我找不到与第二句相对应的任何内容。事实上,类似于(let n n)SBCL 编译器的东西。

这是什么意思?这种用途的最小例子是什么?

4

1 回答 1

14

这是什么意思?

它只是意味着所有这三个都具有相同的效果:

(let ((x nil))      (let ((x))        (let (x)
  x)                  x)                x)

在每种情况下,x都绑定到nil。大多数人都熟悉第一种情况。第二种情况不包括init-form,但 Common Lisp 也被定义为在这种情况下将x绑定到nil。当然,第二种情况,从某种角度来看,有更多你需要的括号(它只是变量周围的一组额外括号),所以你甚至可以采取另一种捷径,只写变量本身。

它在哪里指定?

let的文档中,我们看到let的语法是:

让 ({var | (var [init-form])}*) 声明* 形式* ⇒ 结果*

从那里,我们看到let的每次使用都会看起来像

(let (…) …)

但是那个内部列表是什么?

{变量 | (var [init-form])}*

* 表示该列表中可以有任意数量(零个或多个)事物,并且每个事物都匹配var(var [init-form])。var 只是一个可以用作变量的符号。( var [init-form])是一个列表,它以var作为第一个元素,并且可选地具有第二个元素init-form

但这意味着在两种可能的情况下(var本身和没有 init-form 的列表没有init-form。Common Lisp 没有定义未绑定或未初始化的变量,而是将这些情况下的值定义为nil

为什么允许如此多的变化?其中很多是为了在 Common Lisp 中不同的特殊形式之间保持一致。看看问题 VARIABLE-LIST-ASYMMETRY Writeup。有关阅读文档中的语法规范的更多信息,请查看1.4.4.20 字典条目的“语法”部分

于 2014-09-14T00:04:29.827 回答