Lisp quest discovering a parenthesis world

Lisp lists basics - quoting

You may have heard that Lisp code is all about parentheses - and it is true. But do you really know why Lisp code is made by so many parentheses? Well, the answer is quite simple: Lisp code is just a long sequence of lists and the parentheses are the way these lists are created.

Lisp stands for LISt Processor so it should not be a surprise if its code is full of lists.1 Parentheses are lists’ delimiters, so everything between them is part of a list.

An empty list

Creating a list is simple - just write a single quote character followed by a couple of parentheses.2 This is an empty list:

'()

Simple lists

Creating a list containing items is straightforward. Just add the elements you want between the parentheses, separating them with a whitespace.

'(1)
'(1 2)
'(one two three)
'(a list with mixed content 42 "and a string")

Whitespaces inside a list

As we said, a single whitespace is required to separate list’s items, but there is no limit on the number of whitespace you can add between them. Adding more whitespaces does not have any effect on the list. So you can rewrite the last list in this way and it will be the same as before.

'(a
  list
  with mixed content
  42
  "and a string")

A list inside a list

If you were wondering if you can put a list inside another list, the answer is definitely yes.

'(a list (with another list))

And yes, you can go as deep and complex as you want.

'(a (list) (with (another) list))

Code VS lists

We said that a single quote character is required before the list in order to create it. Indeed, if you try to write one of such lists in the Lisp REPL, it will return you the list itself.

* '(one two three)
(ONE TWO THREE)

And what happens when you try to remove the quote character? Fasten your seatbelts because the output is quite long.

* (one two three)
; in: ONE TWO
;     (ONE TWO THREE)
;
; caught STYLE-WARNING:
;   undefined function: COMMON-LISP-USER::ONE
;
; caught WARNING:
;   undefined variable: COMMON-LISP-USER::THREE
;
; caught WARNING:
;   undefined variable: COMMON-LISP-USER::TWO
;
; compilation unit finished
;   Undefined function:
;     ONE
;   Undefined variables:
;     THREE TWO
;   caught 2 WARNING conditions
;   caught 1 STYLE-WARNING condition

debugger invoked on a UNBOUND-VARIABLE in thread
#<THREAD "main thread" RUNNING {1000510083}>:
The variable TWO is unbound.

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
0: [CONTINUE   ] Retry using TWO.
1: [USE-VALUE  ] Use specified value.
2: [STORE-VALUE] Set specified value and use it.
3: [ABORT      ] Exit debugger, returning to top level.

((LAMBDA ()))
source: (ONE TWO THREE)
0] 3

As you can see from the logs, the Lisp REPL tried to evaluate the list but it failed on the first element - one. It expected to find a function there, but it found the one symbol.3 This is due to the way Lisp works. If a list is not preceded by a single quote character, it will be not evaluated as data, but as code. Indeed, if you try to add a single quote before a list containing a sum, it will not be evaluated.

* (+ 1 2)
3
* '(+ 1 2)
(+ 1 2)

So, the difference between code and data is just that the former is evaluated (“executed”) by the Lisp REPL (or compiler) when read. The latter, instead, is parsed and kept as-is.

The quote operator

Until now we have created lists using the single quote character, but it is just a shortcut for the Lisp special operator quote.4

* (quote (+ 1 2))
(+ 1 2)

Quoting means escaping and also avoiding the evaluation of the quoted expression. You can use the quote special operator to quote almost anything, not only lists.

* (quote a)
a
* (quote 1)
1
* (quote "hello world")
"hello world"

The semantics of the quote operator is “get an object and return it as is, without evaluating it” - and this is the exact definition of the word “quotation”. You should not modify a quoted object since results are unpredictable.

In the next post we will see how to build a mutable list using the plain old function list.

  1. You can have a language specialised in list processing without having to write its code as lists. But having your code written as the data it is able to process enable some powerful features. One of this feature is the ability for the code to change itself - the macro system. We will talk about this in another post. 

  2. The single quote character is also called apostrophe, acute accent or just quote. 

  3. Yes, we will talk about symbols in another post. 

  4. Special operators, special forms… Lisp has a lot of special things that need to be known. We will see them one at a time to avoid overloading our brains.