5
votes

In Common Lisp, it seems like () is a self-evaluating form. That is, it evaluates to itself (or its alias nil). So there would seem to be no need to quote it. But using grep on my quicklisp directory finds numerous instances of '(), written by many different people in many different projects. Is there a technical reason for writing out the quoted version? Common Lisp the Lanugage, 2nd Edition, Section 1.2.2, mentions the stylistic differences where you may want to emphasize empty lists with (), and boolean false with nil, but does not cover this question. One of the examples Steele uses is:

(append '() '())

...which I believe could be written just as well as:

(append () ())

...so why throw the extra QUOTEs in there? Certainly it doesn't hurt things. Stylistically, is one form generally preferred to the other? Someone could certainly make the case that quoted form makes it simpler to add elements to in case you change your mind, and really want a non-empty literal list instead. Or that there is a certain symmetry in using the quote, because a non-empty literal list would also need it.

Is this historical baggage hanging around from other/older related languages that have been carried on by tradition?

This is unlike Scheme, where you do need to quote it. And it seems like you don't have to quote it in elisp, so maybe in a round-about way it could be related to lisp-1 vs. lisp-2?

4

4 Answers

8
votes

The quote has a very informative property, stating clearly that you mean that the token is supposed to be literal data. More so when you or a coworker revisits the code years later.

You must use () (without the quote) to declare an empty list in non-evaluated forms, such as a parameter list or class super-classes and slots, where the quote will actually cause harm. Actually, you can use nil as well, but you shouldn't, for clarity, when the declared thing is a list.


Here's a relevant excerpt from the specification:

1.4.1.4.4 NIL

nil has a variety of meanings. It is a symbol in the COMMON-LISP package with the name "NIL", it is boolean (and generalized boolean) false, it is the empty list, and it is the name of the empty type (a subtype of all types).

Within Common Lisp, nil can be notated interchangeably as either NIL or (). By convention, the choice of notation offers a hint as to which of its many roles it is playing.

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.        

Figure 1-1. Notations for NIL

Within this document only, nil is also sometimes notated as false to emphasize its role as a boolean.

For example:

(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

A function is sometimes said to “be false” or “be true” in some circumstance. Since no function object can be the same as nil and all function objects represent true when viewed as booleans, it would be meaningless to say that the function was literally false and uninteresting to say that it was literally true. Instead, these phrases are just traditional alternative ways of saying that the function “returns false” or “returns true,” respectively.

4
votes

There's a reason to prefer writing '() to () even if () is self-evaluating. It makes the code easier to read because it's visually obvious that you're dealing with a datum, not an evaluated form.

It's similar to the reason to prefer writing '#(foo bar baz (+ 1 2)) to #(foo bar baz (+ 1 2)). Both evaluate to the same thing, but the former makes it visually obvious that the foo, bar, baz, and (+ 1 2) within are not evaluated.

3
votes

I never quote NIL , () or T, and certainly not numbers or strings.

If I read '() in someone's code, I am likely to be confused about the author's intent and maybe his/her understanding of quote in Common Lisp (beginner's question over here tend to show confusion with quotes).

I can't speak about the possibility that some implementations of CL would have needed, at some point, to quote (), but it is more likely that the author has experience with other flavors of Lisp and tries to apply this experience to Common Lisp, out of habit or on purpose.

The only case where I think it could make sense to quote () is when a previously non-empty constant list was emptied and someone did not bother to remove the quote.

(defvar *options* '(debug))

... becomes

(defvar *options* '())

It could even make sense to keep the quote in case you plan to change the defaults later.

2
votes

In Common Lisp () and nil are both representations of nil and it's self evaluating. Everything that is quoted evaluates to it's argument, but since the argument is nil which is self evaluating the result is the same. The compiled code will most likely be identical.

Scheme was originally interpreted under a predecessor to CL and in the first reports they more or less just made a lisp with lexical closure and one namespace and not much more. It looked more like CL than Scheme, but was a LISP1 so the empty list rules cannot be about Lisp1 vs Lisp2 since Scheme was a Lisp1 from the first report that didn't require quoting and has nil as a false value.

For every consecutive version of the report Scheme has been refining its syntax and naming conversions. The revisions did subtle changes and they were not afraid of making breaking changes. They introduced new booleans, changed their names, changed the booolean value of the empty list from false to true, removed nil and t as alias to #t and #f and deemed () an invalid expression thus requiring '().

Since it doesn't matter how you do it in CL perhaps some people who codes in both languages just want to have some symmetry in their lives. I certainly do this, but I cannot speak for all schemers.