Contents | Getting Started | More Lists
And now, meet the list.
A list is a linear arrangement of objects separated by blanks and surrounded by parentheses. The obkects which make up a list are either atoms or other lists. An atom is the basic unit of data understood by the Lisp language.
Here are some atoms.
carbon eve 1 bananastandHere are some lists:
(1 2 3 4) ((i hate) (peanut butter) (and jelly)) (you (walrus (hurt) the (one you) love)) (add 3 (mult 4 5)) (garbage (garbage) out) (car ((in the garage) park)) (deeper and (deeper and (deeper and (deeper we went))))Please note several things.
"you" is an atom.
"(walrus (hurt) the (one you) love)" is a list.
The parts of that list are
"walrus" is an atom.
"(hurt)" is a list with one element: the atom "hurt".
"the" is an atom.
"(one you)" is a list with the elements: "one" and "you", each of these is an atom.
"love" is an atom.
Rules for lists being evaluated:
:(ADD 8 3) 11is a list which is evaluated and has its value printed.
If the first element is not a Lisp function, then an error occurs:
:(1 2 3 4) ** ERROR: BAD ATOMIC ARG ** EVAL :: NIL +() NILWhat if we try to add all the numbers in a list?
:(ADD (1 2)) ** ERROR: BAD ATOMIC ARG ** EVAL :: NIL +() NILCompare the expressions (ADD 1 2) and (ADD (1 2)). In the first one, the ADD function acts on two separate atoms [not a list--no surrounding parentheses] while in the second one ADD acts [or at least tries to act] on a list: (1 2). Remember that Lisp first evaluates the arguments before applying the function.
When Lisp encounters (ADD (1 2)), it first tries to evaluate the argument to ADD, namely the list (1 2). Note that "1" is not a Lisp function. [Remember, if Lisp is trying to evaluate a lista, the first element in the list had better be the name of a Lisp function and the rest of the list had better be the arguments to that function or else TROUBLE!!]
Here, again, NIL ["()"] is used to get back to the normal Lisp prompt ":".
We would like to be able to use lists like "(A B C)", to represent data in Lisp. Unfortunately Lisp seems to want to evaluate everything that we enter. Since there is likely no "A" function, the evaluation of the list will cause an error. This leaves us in a bit of a quagmire!
Good fortune has fallen upon you. There is a way to stop Lisp from trying to evaluate a list. The quote character ['] causes Lisp to take the expression as written rather than to try to evaluate it. We're going to begin applying the quote quite liberally from now on. Be very careful to watch what does and does not get evaluated.
:'(DO NOT (EAT ANYTHING) NOW)) ( DO NOT (EAT ( ANYTHING ) NOW ) ) :'(MULT (ADD 1 2) 4) ( MULT (ADD 1 2 ) 4 )Let's introduce some Lisp functions which manipulate lists. Manipulating involves taking apart, putting together, and checking the values of lists. The two functions CAR and CDR are used to get parts out of lists. The CAR function returns the first element in a list.
:(CAR '(1 2 3 4)) 1 :(CAR '((I HATE) (PEANUT BUTTER) (AND JELLY))) ( I HATE ) :(CAR 1) ** ERROR: BAD ATOMIC ARG ** CAR :: (1 ) +() NILNote that the result of a CAR need not be an atom [in the second case above, it is a list of two atoms], but that CAR is only designed to take arguments which are lists, not atoms.
CDR [pronounced "could-er"] is the complement of CAR in that the result of CDR is the "rest" of the list:
:(CDR '(1 2 3 4)) ( 2 3 4 ) :(CDR '(FUN FROG)) ( FROG ) :(CDR '((THREE BLIND) MACE)) ( MACE ) :(CDR '(HELLO)) NIL :(CDR '()) NILLike CAR, CDR is defined only to operate on lists. Unlike CAR, however, the value of CDR is ALWAYS a list. Note that the CDR of a list with only one element is an empty list [written as () or NIL].
We have, in the previous pages, listed the following seemingly contradictory characteristics of NIL:
NIL is certainly making a lot of trouble for such an empty concept. Why should we make so much ado about nothing? NIL is in fact the most important entity in the Lisp language. It is both an atom and a list, depending upon who is doing the asking. It can be returned by functions whose value is defined to be an atom, such as a predicate, or by functions whose value is defined to be a list, such as CDR. NIL is an empty list [a list with no elements]. The use of NIL will become clearer when we begin studying user defined functions in a later chapter.
Back to the business at hand: CAR and CDR.
We saw in the first chapter that subexpressions can be used in place of the arguments of any function. In the same way, the list processing functions can be combined to do various list operations.
:(CDR '(SAND WITCH)) ( WITCH ) :(CDR (CDR '(SAND WITCH))) NIL :(CDR (CDR (CDR '(SAND WITCH)))) NIL :(CAR (CDR '(SAND WITCH))) WITCH :(CAR (CAR (CDR '(() ((BOZO) ( NO NO)))))) ( BOZO ) :(CDR (CAR (CDR '(() ((BOZO) (NO NO)))))) ( (NO NO ) ) :(CAR (CAR (CDR (CAR (CDR '(() ((BOZO) (NO NO)))))))) NO :(CDR (CAR '((CAR CDR) CAR))) ( CDR ) :(CAR '(ADD 1 2)) ADD :(CDR '(ADD 1 2)) ( 1 2 )As we mentioned a little earlier in this chapter, the expressions that we are typing into Lisp are lists, just as "(1 2 3 4)" is a list. Remember functions and arguments? Well, the CAR of an expression-list is its function name and the CDR of that expression-list is the list of the arguments to that function!
There are standard abbreviations for up to four successive applications of CAR/CDR combinations: take the letter "A" from every CAR and "D" from every CDR and place them next to each other sandwiched between a "C" and an "R" [NOTE: Lisp aficionados claim to be able to pronounce all 28 combinations of CAR and CDR]. For example, the expression (CADDR ANYLIST) is the same as the longer expression (CAR (CDR (CDR ANYLIST))). This book will not use these too much, but you should be familiar with them since many things written in Lisp do use them. The above example
:(cdr (car (cdr '() ((bozo) (no no))))))could have been written
:(CDADR ' (() ((BOZO) (NO NO)))) ( (NO NO ) )
Contents | Getting Started | More Lists