In Common LISP, use eql instead of eq, since Common LISP allows implementations to make copies of numbers and characters for efficiency purposes. Two objects are eql if they are eq, or if they are numbers of the same type with the same value, or if they are character objects that represent the same character.
The list is the only composite data type in classical LISP; Common LISP also has strings, vectors, arrays, streams, . . .
NOTE: cons is the inverse of car and cdr.
E.g.,
>
(cons 'a '(b c))
(A B C)
>
(car (cons 'a '(b c)))
A
>
(cdr (cons 'a '(b c)))
(B C)
Historical note: car = "contents of address field of register" and cdr = "contents of decrement field of register" [IBM 704].
c { a | d }+ r
[Length may be limited; e.g., Common LISP restricts combinations to four
a's and d's.]
car
cdr
E.g., (a b c)
|
---> |
|
---> |
|
||||||
| | v a |
| v b |
| v c |
E.g., (a (b c) d)
|
-----> |
|
----------> |
|
||||||||
| | v a |
| | v |
| v d |
||||||||||
|
---> |
|
||||||||||
| | v b |
| v c |
|||||||||||
Alternate notation: dotted pairs
E.g.,
>
(cons 'a 'b)
(A . B)
|
---> b | ||
| | v a |
List reading and printing facilities (read and print) are designed to simplify
the notation of a dotted pair to list form when possible.
E.g.,
>
'(a . nil)
(A)
Shared sublists are efficient and transparent
E.g.,
>
(set 'aList '(a c d))
(A C D)
| aList ----> |
|
---> |
|
---> |
|
||||||
| | v a |
| v c |
| v d |
>
(set 'bList '(b c))
(B C)
| ^ | |||||||
| | | |||||||
| bList ----> |
|
---> |
|
||||
| | v b |
|||||||
>
(set 'cList (cons (car bList) (cdr aList)))
(B C D)
| ^ | ||||
| | | ||||
| cList ----> |
|
-- · · · --> [points to second cons cell of aList] |
This is a form of aliasing: there is more than one named path to a memory location.
If the node pointing to atom c is changed by access through aList, then cList is also changed. Since car, cdr, and cons are pure functions (with no side effects), they cannot change this node.
However, there are two functions which have the side effect of changing a node:
E.g.,
>
(rplacd (cdr aList) bList)
(C B C)
>
aList
(A C B C)
>
bList
(B C)
>
cList
(B C B C)
This makes infinite loops possible.
E.g.,
>
(set 'x '(y z))
(Y Z)
| x ----> |
|
---> |
|
||||
| | v y |
| v z |
>
(rplacd (cdr x) x)
(Z Y Z Y Z Y Z Y . . .
| v--- | ---- | ---| | |||||
| x ----> |
|
---> |
|
||||
| | v y |
| v z |
Print name (pname or "print-name cell") is unique for each atom.
Address is unique for each atom.
E.g.,
>
(eq (car '(a b c)) (cadr '(b a d)))
T
An atom may have a value (apval, for applied value, or "value cell"), bound by set.
An atom may be defined as a function (expr, or "function cell") using defun.
An atom may have user-defined properties: each atom has a pointer to a property list.
E.g.,
>
(putprop 'chair 'blue 'colour)
or
(put 'chair 'colour 'blue)
Common LISP: (setf (get 'chair 'colour) 'blue)
BLUE
>
(get 'chair 'colour)
BLUE
Atoms are represented differently on different systems.
An implementation may use a regular cons cell with an illegal left pointer (e.g., -1) to designate an atom, with a right pointer to a property list.
An implementation may use a special structure, such as a record consisting of several pointers: one to the atom's print name, one to its applied value, one to its function expression, and one to its property list.