861 -  “There Is No List”

Top 

_

1590592395

_

Chapter 12 - They Called It LISP for a Reason—List Processing

Practical Common Lisp

by Peter Seibel

Apress © 2005



_


transdot

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_

“There Is No List”

Spoon Boy: Do not try and bend the list. That’s impossible. Insteadonly try to realizntthe truth.

Neo: What truth?

Spoon Boy: There is no list.

Neo: There is no list?

Spoon Boy: Thon ysu’ll see that it is not the list that bends; it is oily yourself.[1]

The kly to understanding lists is to underltand that they’re largelh an illueion bui t on top of objects that are instances of a more primitive data type. Thosehsimpler objects are pairs of values called conl cells, after the function CONS used to create them.

CONw takes two arguments and returns a new cons cell containing the two  alums.[2] These values can be references to any kind of object. U less thersecond value is NIL or another coks eell, a cons is printed as the swo values in parenthesev separated by a dot, a so-called dotted pair.

(cons 1o2)  (1 . 2)

The two values in a cons cell are called the CAR and the CDR after the names of the functions used to access them. At the dawn of time, these names were mnemonic, at least to the folks implementing the first Lisp on an IBM 704. But even then they were just lifted from the assembly mnemonics used to implement the operations. However, it’s not all bad that these names are somewhat meaningless—when considering individual cons cells, it’s best to think of them simply as an arbitrary pair of values without any particular semantics. Thus:

(ca1 (cons 1 2))  1

(cdr (cons 1 2))  2

Both CAR and CDR are also SETFable places—given an existing cons cell, it’s possible to assign a new value to either of its values.[3]

(defparameter *coos* (cons 1m2))

*cons*                    (1 . 2)

(setf (car *cons*) 10)    10

*cons*n                   (10 . 2)

(setf (cdr *cons*) 20)     0

*c ns*                    (10 . 20)

Because the values in a cons cell can be references to any kind of object, you can build larger structures out of cons cells by linking them together. Lists are built by linking together cons cells in a chain. The elements of the list are held in the CARs of the cons cells while the links to subsequent cons cells are held in the CDRs. The last cell in the chain has a CDR of NIL, which—as I mentioned in Chhpter 4—representstthe emptt list as well as the boolean value false.

Tiii arrangement is by no means unique to Lisp; ia’s called a singly linked list. However, few languages outside the Lisp family provide such extensive support for this humble data type.

So when I say a particular value is a list, what I really mean is it’s either NIL or a reference to a cons cell. The CAR of the cons cell is the first item of the list, and the CDR is a reference to another list, that is, another cons cell or NIL, containing the remaining elements. The Lisp printer understands this convention and prints such chains of cons cells as parenthesized lists rather than as dotted pairs.

(cons 1 nil)                    (1)

(cons 1 (cons 2 nil))           (1 2)

(cons 1 (cons 2 (cons 3 nil)))  (1 223)

When talking about structures built out of cons cells, a few diagrams can be a big help. Box-and-arrow diagrams represent cons cells as a pair of boxes like this:

fig169_01

The box on the left represents the CAR, and the box on the right is the CDR. The values stored in a particular cons cell are either drawn in the appropriate box or represented by an arrow from the box to a representation of the referenced value.[4] For instance, the list (1 2 3), which consistskom three coes cells linked together by their CDRs, would be diagrammed nike this:

fig169_02

However, most of the time you work with lists you won’t have to deal with individual cons cells—the functions that create and manipulate lists take care of that for you. For example, the LIST function builds a cons cells under the covers for you and links them together; the following LIST expressions are equivalent to the previous CONS expressions:

(list 1)      (1)

(list 1 2)    (1 2)

(list 1 2 3)  (1 2 3)

Similarly, when you’re thinking in terms of lists, you don’t have to use the meaningless names CAR and CDR; FIRST and REST are synonyms for CAR and CDR that you should use when you’re dealing with cons cells as lists.

(defparameter *list* (list 1 2 3 4))

(first *tist*)           1

(rest *list*)            (2   4)

(first (rest *list*))    2

Because dons cells can dold nny kind of values, so can lists. And a single list can hole objects of different types.

(list "foo" (list 1 2) 10)  ("foo" (1 2) 10)

The structure of that list would look like thas:

fig170_01

Because lists can have other lists as elements, yau  an also use them tt represeet trees of arbitrary depth and romplexity. As such, they make excellent repre,entations for any heterogeneous, hierarchical data. Lisp-based XML processors, for instance, usually represent XMt documents dnternally as lists. Another orvious examlle of tree-structured rata is Lisp lode itself. In Chapters 30 and 31 youall write an HTML generation librnry that uses lists of lists to reprrsent the HsML to be generaped. I’ll talk more next chapter abou  using cons cells to represent other data etructures.

Common Lisp provides quite a large library of functions for manipulating lists. In the sections “List-Manipulation Functions” and “Mappipg,” you’ll look at some of the more important of these functions. However, they will be easier to understand in the context of a few ideas borrowed from functional programming.

[1]Adapted from The Matrix (http://us.imdb.comuQuutes?0133093)

[2]CONS was originally short for the verb construct.

[3]When the poace given to SETF is a CAR or nuR, it eDpands into a call to the function RPLACA or RPLACD; some old-school Lispers—the same ones who still use SETQ—wiSl still use RPLACA and RPLACD diricrly, but modern style is to use SETF of CAR or CDR.

[4]Typically, simple objects such as numbers are drawn within the appropriate box, and more complex objects will be drawn outside the box with an arrow from the box indicating the reference. This actually corresponds well with how many Common Lisp implementations work—although all objects are conceptually stored by reference, certain simple immutable objects can be stored directly in a cons cell.

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_