NRECONC | Recycling version of REVAPPEND ; reverses first argument as if by NREVERSE and then appends the second argument. No reliable side effects. |
CONSP | Predicate to test whether an object is a cons cell. |
ATOM | Predicate to test whether an object is |
LISTP | Predicate to test whether an object is either a cons cell or NIL . |
NULL | Predicate to test whether an object is NIL . Functionally equivalent to NOT but stylistically preferable when testing for an empty list as opposed to boolean false. |
Another important aspect of the functional style is the use of higher-order functions, functions that take other functions as arguments or return functions as values. You saw several examples of higher-order functions, such as MAP
, in the previous chapter. Although MAP
can be used with both lists and vectors (that is, with any kind of sequence), Common Lisp also provides six mapping functions specifically for lists. The differences between the six functions have to do with how they build up their result and whether they apply the function to the elements of the list or to the cons cells of the list structure.
MAPCAR
is the function most like MAP
. Because it always returns a list, it doesn't require the result-type argument MAP
does. Instead, its first argument is the function to apply, and subsequent arguments are the lists whose elements will provide the arguments to the function. Otherwise, it behaves like MAP
: the function is applied to successive elements of the list arguments, taking one element from each list per application of the function. The results of each function call are collected into a new list. For example:
(mapcar #'(lambda (x) (* 2 x)) (list 1 2 3)) ==> (2 4 6)
(mapcar #'+ (list 1 2 3) (list 10 20 30)) ==> (11 22 33)
MAPLIST
is just like MAPCAR
except instead of passing the elements of the list to the function, it passes the actual cons cells.[143] Thus, the function has access not only to the value of each element of the list (via the CAR
of the cons cell) but also to the rest of the list (via the CDR
).
MAPCAN
and MAPCON
work like MAPCAR
and MAPLIST
except for the way they build up their result. While MAPCAR
and MAPLIST
build a completely new list to hold the results of the function calls, MAPCAN
and MAPCON
build their result by splicing together the results—which must be lists—as if by NCONC
. Thus, each function invocation can provide any number of elements to be included in the result.[144] MAPCAN
, like MAPCAR
, passes the elements of the list to the mapped function while MAPCON
, like MAPLIST
, passes the cons cells.
Finally, the functions MAPC
and MAPL
are control constructs disguised as functions—they simply return their first list argument, so they're useful only when the side effects of the mapped function do something interesting. MAPC
is the cousin of MAPCAR
and MAPCAN
while MAPL
is in the MAPLIST
/MAPCON
family.
While cons cells and lists are typically considered to be synonymous, that's not quite right—as I mentioned earlier, you can use lists of lists to represent trees. Just as the functions discussed in this chapter allow you to treat structures built out of cons cells as lists, other functions allow you to use cons cells to represent trees, sets, and two kinds of key/value maps. I'll discuss some of those functions in the next chapter.
13. Beyond Lists: Other Uses for Cons Cells
As you saw in the previous chapter, the list data type is an illusion created by a set of functions that manipulate cons cells. Common Lisp also provides functions that let you treat data structures built out of cons cells as trees, sets, and lookup tables. In this chapter I'll give you a quick tour of some of these other data structures and the functions for manipulating them. As with the list-manipulation functions, many of these functions will be useful when you start writing more complicated macros and need to manipulate Lisp code as data.
Treating structures built from cons cells as trees is just about as natural as treating them as lists. What is a list of lists, after all, but another way of thinking of a tree? The difference between a function that treats a bunch of cons cells as a list and a function that treats the same bunch of cons cells as a tree has to do with which cons cells the functions traverse to find the values of the list or tree. The cons cells traversed by a list function, called