Common Lisp:普通变量是LET中列表的简写



我正在阅读Gigamonkey(Peter Seibel)的实用公共Lisp,在宏一章中关于DO的部分中遇到了以下声明:

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

我不知道他说的"用一个普通变量作为一个只包含名字的列表的缩写"是什么意思,也就是第二句。第一句话在LET的Common Lisp Hyperspec中得到了支持,还有一个像(let (n) n) ~~> NIL这样的简单例子,但我找不到任何与第二句相对应的内容。事实上,类似(let n n)的东西会触发SBCL编译器。

这是什么意思?这种用法的最小示例是什么?

这是什么意思

这只是意味着这三种方法都有相同的效果:

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

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

具体规定在哪里

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

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

从中,我们可以看到let的每次使用都会看起来像

(let (…) …)

但这份内部清单中包含了什么?

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

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

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

为什么允许这么多变化?这在很大程度上是为了在Common Lisp中保持不同特殊形式之间的一致性。查看Issue VARIABLE-LIST-ASYMETRY Writeup。有关阅读文档中语法规范的更多信息,请参阅1.4.4.20字典条目的"语法"部分。

最新更新