Skip to main content

2.4.6 Cons Cell and List Types

A cons cell is an object that consists of two slots, called the CAR slot and the CDR slot. Each slot can hold any Lisp object. We also say that the CAR of this cons cell is whatever object its CAR slot currently holds, and likewise for the CDR.

A list is a series of cons cells, linked together so that the CDR slot of each cons cell holds either the next cons cell or the empty list. The empty list is actually the symbol nil. See Lists, for details. Because most cons cells are used as part of lists, we refer to any structure made out of cons cells as a list structure.

A note to C programmers: a Lisp list thus works as a linked list built up of cons cells. Because pointers in Lisp are implicit, we do not distinguish between a cons cell slot holding a value versus pointing to the value.

Because cons cells are so central to Lisp, we also have a word for an object which is not a cons cell. These objects are called atoms.

The read syntax and printed representation for lists are identical, and consist of a left parenthesis, an arbitrary number of elements, and a right parenthesis. Here are examples of lists:

(A 2 "A")            ; A list of three elements.
() ; A list of no elements (the empty list).
nil ; A list of no elements (the empty list).
("A ()") ; A list of one element: the string "A ()".
(A ()) ; A list of two elements: A and the empty list.
(A nil) ; Equivalent to the previous.
((A B C)) ; A list of one element
; (which is a list of three elements).

Upon reading, each object inside the parentheses becomes an element of the list. That is, a cons cell is made for each element. The CAR slot of the cons cell holds the element, and its CDR slot refers to the next cons cell of the list, which holds the next element in the list. The CDR slot of the last cons cell is set to hold nil.

The names CAR and CDR derive from the history of Lisp. The original Lisp implementation ran on an IBM 704 computer which divided words into two parts, the address and the decrement; CAR was an instruction to extract the contents of the address part of a register, and CDR an instruction to extract the contents of the decrement. By contrast, cons cells are named for the function cons that creates them, which in turn was named for its purpose, the construction of cells.

• Box Diagrams  Drawing pictures of lists.
• Dotted Pair Notation  A general syntax for cons cells.
• Association List Type  A specially constructed list.

2.4.6.1 Drawing Lists as Box Diagrams​

A list can be illustrated by a diagram in which the cons cells are shown as pairs of boxes, like dominoes. (The Lisp reader cannot read such an illustration; unlike the textual notation, which can be understood by both humans and computers, the box illustrations can be understood only by humans.) This picture represents the three-element list (rose violet buttercup):

    --- ---      --- ---      --- ---
| | |--> | | |--> | | |--> nil
--- --- --- --- --- ---
| | |
| | |
--> rose --> violet --> buttercup

In this diagram, each box represents a slot that can hold or refer to any Lisp object. Each pair of boxes represents a cons cell. Each arrow represents a reference to a Lisp object, either an atom or another cons cell.

In this example, the first box, which holds the CAR of the first cons cell, refers to or holds rose (a symbol). The second box, holding the CDR of the first cons cell, refers to the next pair of boxes, the second cons cell. The CAR of the second cons cell is violet, and its CDR is the third cons cell. The CDR of the third (and last) cons cell is nil.

Here is another diagram of the same list, (rose violet buttercup), sketched in a different manner:

 ---------------       ----------------       -------------------
| car | cdr | | car | cdr | | car | cdr |
| rose | o-------->| violet | o-------->| buttercup | nil |
| | | | | | | | |
--------------- ---------------- -------------------

A list with no elements in it is the empty list; it is identical to the symbol nil. In other words, nil is both a symbol and a list.

Here is the list (A ()), or equivalently (A nil), depicted with boxes and arrows:

    --- ---      --- ---
| | |--> | | |--> nil
--- --- --- ---
| |
| |
--> A --> nil

Here is a more complex illustration, showing the three-element list, ((pine needles) oak maple), the first element of which is a two-element list:

    --- ---      --- ---      --- ---
| | |--> | | |--> | | |--> nil
--- --- --- --- --- ---
| | |
| | |
| --> oak --> maple
|
| --- --- --- ---
--> | | |--> | | |--> nil
--- --- --- ---
| |
| |
--> pine --> needles

The same list represented in the second box notation looks like this:

 --------------       --------------       --------------
| car | cdr | | car | cdr | | car | cdr |
| o | o------->| oak | o------->| maple | nil |
| | | | | | | | | |
-- | --------- -------------- --------------
|
|
| -------------- ----------------
| | car | cdr | | car | cdr |
------>| pine | o------->| needles | nil |
| | | | | |
-------------- ----------------

2.4.6.2 Dotted Pair Notation​

Dotted pair notation is a general syntax for cons cells that represents the CAR and CDR explicitly. In this syntax, (a . b) stands for a cons cell whose CAR is the object a and whose CDR is the object b. Dotted pair notation is more general than list syntax because the CDR does not have to be a list. However, it is more cumbersome in cases where list syntax would work. In dotted pair notation, the list ‘(1 2 3)’ is written as ‘(1 . (2 . (3 . nil)))’. For nil-terminated lists, you can use either notation, but list notation is usually clearer and more convenient. When printing a list, the dotted pair notation is only used if the CDR of a cons cell is not a list.

Here’s an example using boxes to illustrate dotted pair notation. This example shows the pair (rose . violet):

    --- ---
| | |--> violet
--- ---
|
|
--> rose

You can combine dotted pair notation with list notation to represent conveniently a chain of cons cells with a non-nil final CDR. You write a dot after the last element of the list, followed by the CDR of the final cons cell. For example, (rose violet . buttercup) is equivalent to (rose . (violet . buttercup)). The object looks like this:

    --- ---      --- ---
| | |--> | | |--> buttercup
--- --- --- ---
| |
| |
--> rose --> violet

The syntax (rose . violet . buttercup) is invalid because there is nothing that it could mean. If anything, it would say to put buttercup in the CDR of a cons cell whose CDR is already used for violet.

The list (rose violet) is equivalent to (rose . (violet)), and looks like this:

    --- ---      --- ---
| | |--> | | |--> nil
--- --- --- ---
| |
| |
--> rose --> violet

Similarly, the three-element list (rose violet buttercup) is equivalent to (rose . (violet . (buttercup))). It looks like this:

    --- ---      --- ---      --- ---
| | |--> | | |--> | | |--> nil
--- --- --- --- --- ---
| | |
| | |
--> rose --> violet --> buttercup

2.4.6.3 Association List Type​

An association list or alist is a specially-constructed list whose elements are cons cells. In each element, the CAR is considered a key, and the CDR is considered an associated value. (In some cases, the associated value is stored in the CAR of the CDR.) Association lists are often used as stacks, since it is easy to add or remove associations at the front of the list.

For example,

(setq alist-of-colors
'((rose . red) (lily . white) (buttercup . yellow)))

sets the variable alist-of-colors to an alist of three elements. In the first element, rose is the key and red is the value.

See Association Lists, for a further explanation of alists and for functions that work on alists. See Hash Tables, for another kind of lookup table, which is much faster for handling a large number of keys.