Common Lisp中的#39;()vs()

时间:2016-05-24 22:15:53

标签: lisp common-lisp language-lawyer empty-list

在Common Lisp中,似乎()是一种自我评估的形式。也就是说,它评估自身(或其别名nil)。所以似乎没有必要引用它。但是在我的quicklisp目录中使用grep可以找到许多'()的实例,这些实例由许多不同项目的许多不同的人编写。写出引用版本有技术原因吗? Common Lisp the Lanugage, 2nd EditionSection 1.2.2,提及您可能希望使用()强调空列表的样式差异,并使用nil强调布尔值假,但不包括此问题。 Steele使用的一个例子是:

(append '() '())

...我认为可以写得和以下一样:

(append () ())

...为什么要在那里抛出额外的QUOTEs?当然它不会伤害事物。在风格上,一种形式通常优先于另一种形式?有人可以肯定地说,引用表单使得添加元素变得更简单,以防你改变主意,并且真的想要一个非空的文字列表。或者使用引号存在一定的对称性,因为非空的文字列表也需要它。

这些历史包袱是否与传统中传承的其他/较旧的相关语言有关?

这与Scheme不同,您需要引用它。而且似乎你不必在elisp中引用它,所以也许它可能与lisp-1和lisp-2有关。

4 个答案:

答案 0 :(得分:7)

引用有一个非常有用的属性,清楚地表明你的意思是令牌应该是文字数据。当你或同事多年后重新访问代码时更是如此。

您必须使用()(不带引号)在非评估表单中声明一个空列表,例如参数列表或类超类和插槽,其中引号实际上会造成损害。实际上,您也可以使用nil,但为了清楚起见,您不应该在声明的内容是列表时使用。

以下是the specification的相关摘录:

  

1.4.1.4.4 NIL

     

nil有多种含义。它是COMMON-LISP包中的符号,名称为"NIL",它是boolean(和泛化布尔值)false,它是空列表,它是空类型的名称(子类型为所有类型)。

     

在Common Lisp中,nil可以互换为NIL()。按照惯例,符号的选择提供了一个关于它正在扮演的角色中的哪一个的暗示。

For Evaluation?  Notation  Typically Implied Role       
----------
Yes              nil       use as a boolean.            
Yes              'nil      use as a symbol.             
Yes              '()       use as an empty list         
No               nil       use as a symbol or boolean.  
No               ()        use as an empty list.        
     

图1-1。 NIL的符号

     

仅在此文档中,nil有时也会被标记为false,以强调其作为布尔值的作用。

     

例如:

(print ())                          ;avoided
(defun three nil 3)                 ;avoided 
'(nil nil)                          ;list of two symbols
'(() ())                            ;list of empty lists
(defun three () 3)                  ;Emphasize empty parameter list.
(append '() '()) =>  ()              ;Emphasize use of empty lists
(not nil) =>  true                   ;Emphasize use as Boolean false
(get 'nil 'color)                   ;Emphasize use as a symbol
     

在某些情况下,某项功能有时被称为“假”或“属实”。由于没有任何函数对象可以与nil相同,并且所有函数对象在被视为布尔值时都表示为真,因此说该函数实际上是错误的并且无趣地说它实际上是真的是毫无意义的。相反,这些短语只是分别表示函数“返回false”或“返回true”的传统替代方式。

答案 1 :(得分:4)

即使'()进行自我评估,也有理由更愿意将()写入()。它使代码更易于阅读,因为在视觉上显而易见的是您处理的是数据,而不是评估的表单。

这类似于更喜欢将'#(foo bar baz (+ 1 2))写入#(foo bar baz (+ 1 2))的原因。两者都评价相同的东西,但前者使得在视觉上明显不评估其中的foobarbaz(+ 1 2)

答案 2 :(得分:3)

我从不引用NIL()T,当然也不引用数字或字符串。

如果我在某人的代码中阅读'(),我可能会对作者的意图感到困惑,也许他/她对Common Lisp中引用的理解(初学者的问题在这里倾向于与引号混淆)。 / p>

我不能谈论CL的某些实现在某些时候需要引用()的可能性,但是更有可能的是作者有其他类型的Lisp的经验并试图出于习惯或故意将此经验应用于Common Lisp。

我认为引用()是有意义的唯一情况是当一个先前非空的常量列表被清空并且有人不愿意删除引用时。

(defvar *options* '(debug))

...变成

(defvar *options* '())

如果您打算稍后更改默认值,保留报价甚至是有意义的。

答案 3 :(得分:2)

在Common Lisp中()nil都是nil的表示,它是自我评估。引用的所有内容都会评估它的参数,但由于参数是nil,它是自我评估的结果是相同的。编译后的代码很可能是相同的。

Scheme最初是在CL的前身下解释的,在第一个报告中,它们或多或少只是用词法闭包和一个命名空间而不是更多。它看起来更像CL而不是Scheme,但它是一个LISP1所以空列表规则不能是关于Lisp1 vs Lisp2,因为Scheme是第一个报告中的Lisp1,它不需要引用并且nil为假值。

对于报告的每个连续版本,Scheme都在改进其语法和命名转换。这些修改做了微妙的改变,他们并不害怕做出重大改变。他们引入了新的布尔值,更改了名称,将空列表的booolean值从false更改为true,将nilt删除为#t#f的别名并视为()无效的表达式因此需要'()

因为你在CL中的表现并不重要,也许一些用两种语言编码的人只想在他们的生活中有一些对称性。我当然这样做,但我不能代表所有阴谋家。