Example: (car '(a b c)) => a
Example: (cdr '(a b c)) => (b c)
car-number = 0 | car of a number is an error. This is the default. |
car-number = 1 | car of a number is nil . |
cdr-number = 0 | cdr of a number is an error. This is the default. |
cdr-number = 1 | cdr of a number is nil . |
car-symbol = 0 | car of a symbol is an error. |
car-symbol = 1 | car of nil is nil , but the car of any other symbol is an error. This is the default. |
car-symbol = 2 | car of any symbol is nil . |
car-symbol = 3 | car of a symbol is its print-name. |
cdr-symbol = 0 | cdr of a symbol is an error. |
cdr-symbol = 1 | cdr of nil is nil , but the cdr of any other symbol is an error. This is the default. |
cdr-symbol = 2 | cdr of any symbol is nil . |
cdr-symbol = 3 | cdr of nil is nil , cdr of any other symbol is its property list. |
All of the compositions of up to four car 's and cdr 's are defined as functions in their own right. The names of these functions begin with "c " and end with "r ", and in between is a sequence of "a "'s and "d "'s corresponding to the composition performed by the function.
Example: (cddadr x) is the same as (cdr (cdr (car (cdr x))))The error checking for these functions is exactly the same as for car and cdr above.
Examples: (cons 'a 'b) => (a . b) (cons 'a (cons 'b (cons 'c nil))) => (a b c) (cons 'a '(b c d)) => (a b c d)
Example: (xcons 'a 'b) => (b . a)There are two reasons this exists: one is that you might want the arguments to cons evaluated in the other order, and the other is that the compiler might convert calls to cons into calls to xcons for efficiency. In fact, it doesn't.
This function creates a cons in a specific area . (Areas are an advanced feature of storage management; if you aren't interested in them, you can safely skip all this stuff). The first two arguments are the same as the two arguments to cons , and the third is the number of the area in which to create the cons .
Example: (cons-in-area 'a 'b my-area) => (a . b)
The following section explains some of the basic functions provided for dealing with lists . There has been some confusion about the term list ever since the beginnings of the language: for the purposes of the following descriptions, a list is the symbol nil , or a cons whose cdr is a list. Note well that although we consider nil to be a list (the list of zero elements), it is a symbol and not a cons, and the listp predicate is not true of it (but perhaps listp will be changed in the future).
Example: (setq x '(a b c d)) (last x) => (d) (rplacd (last x) '(e f)) x => '(a b c d e f)last could have been defined by:
(defun last (x) (cond ((atom x) x) ((atom (cdr x)) x) ((last (cdr x))) ))
Examples: (length nil) => 0 (length '(a b c d)) => 4 (length '(a (b c) d)) => 3length could have been defined by:
(defun length (x) (cond ((atom x) 0) ((1+ (length (cdr x)))) )) or by: (defun length (x) (do ((n 0 (1+ n)) (y x (cdr y))) ((atom y) n) ))
(first x) ==> (car x) (second x) ==> (cadr x) (third x) ==> (caddr x) (fourth x) ==> (cadddr x) etc.
(rest1 x) ==> (cdr x) (rest2 x) ==> (cddr x) (rest3 x) ==> (cdddr x) (rest4 x) ==> (cddddr x)
Examples: (nth 1 '(foo bar gack)) => bar (nth 3 '(foo bar gack)) => nilNote: this is not the same as the InterLisp function called nth , which is similar to but not exactly the same as the Lisp Machine function nthcdr . Also, some people have used macros and functions called nth of their own in their Maclisp programs, which may not work the same way; be careful. nth could have been defined by:
(defun nth (n list) (do ((i n (1- i)) (l list (cdr l))) ((zerop i) (car l))))
Examples: (nthcdr 0 '(a b c)) => (a b c) (nthcdr 2 '(a b c)) => (c)In other words, it returns the n 'th cdr of the list. This is the similar to InterLisp's function nth , except that the InterLisp function is one-based instead of zero-based; see the InterLisp manual for details. nthcdr is defined by:
(defun nthcdr (n list) (do ((i 0 (1+ i)) (list list (cdr list))) ((= i n) list)))
Example: (list 3 4 'a (car '(b . c)) (+ 6 -2)) => (3 4 a b 4)list could have been defined by:
(defun list (&rest args) (let ((list (make-list default-cons-area (length args)))) (do ((l list (cdr l)) (a args (cdr a))) ((null a) list) (rplaca l (car a)))))
Example: (list* 'a 'b 'c 'd) => (a b c . d) This is like (cons 'a (cons 'b (cons 'c 'd)))
Example: (make-list default-cons-area 3) => (nil nil nil)Of course, this function is not usually used when the value of the second argument is a constant; if you want a list of three nil s, it is easy enough to type (nil nil nil) . make-list is used when the number of elements is to be computed while the program is being run. make-list and cons are the two primitive list-creation functions which all the other functions call. The difference is that make-list creates a cdr-coded list (see this link).
(mapcar (function +) foo (circular-list 5))which adds each element of foo to 5.
Example: (append '(a b c) '(d e f) nil '(g)) => (a b c d e f g)Note that append copies the top-level list structure of each of its arguments except the last. Thus, to copy a list but not its elements, use (append x nil) . The copylist function is equivalent. A version of append which only accepts two arguments could have been defined by:
(defun append2 (x y) (cond ((null x) y) ((cons (car x) (append2 (cdr x) y)) )))The generalization to any number of arguments could then be made:
(defun append (&rest args) (and args (append2 (car args) (apply (function append) (cdr args)))))These definitions do not express the full functionality of append ; the real definition minimizes storage utilization by cdr-coding the list it produces, using cdr-next except at the end where a full node is used to link to the last argument, unless the last argument was nil in which case cdr-nil is used.
Example: (reverse '(a b (c d) e)) => (e (c d) b a)reverse could have been defined by:
(defun reverse (x) (do ((l x (cdr l)) ; scan down argument, (r nil ; putting each element (cons (car l) r))) ; into list, until ((null l) r))) ; no more elements.
Example: (setq x '(a b c)) (setq y '(d e f)) (nconc x y) => (a b c d e f) x => (a b c d e f)Note that the value of x is now different, since its last cons has been rplacd 'd to the value of y . If the nconc form is evaluated again, it would yield a piece of "circular" list structure, whose printed representation would be (a b c d e f d e f d e f ...) , repeating forever. nconc could have been defined by:
(defun nconc (x y) ;for simplicity, this definition (cond ((null x) y) ;only works for 2 arguments. (t (rplacd (last x) y) ;hook y onto x x))) ;and return the modified x.
Example: (nreverse '(a b c)) => (c b a)nreverse could have been defined by:
(defun nreverse (x) (cond ((null x) nil) ((nreverse1 x nil)))) (defun nreverse1 (x y) ;auxiliary function (cond ((null (cdr x)) (rplacd x y)) ((nreverse1 (cdr x) (rplacd x y))))) ;; this last call depends on order of argument evaluation.Currently, nreverse does something inefficient with cdr-coded lists, however this will be changed. In the meantime reverse might be preferable in some cases.
(defun nreconc (x y) (cond ((null x) y) ((nreverse1 x y)) ))using the same nreverse1 as above.
(push (hairy-function x y z) variable)replaces the commonly-used construct
(setq variable (cons (hairy-function x y z) variable))and is intended to be more explicit and esthetic. In general, (push item place) expands into (setf place (cons item place)) . (See LINK:(setf-fun) for an explanation of setf .)
Example: (setq x '(a b c)) (pop x) => a x => (b c)In general, (pop place) expands into (prog1 (car place) (setf place (cdr place))) . (See LINK:(setf-fun) for an explanation of setf .)
Examples: (butlast '(a b c d)) => (a b c) (butlast '((a b) (c d)) => ((a b)) (butlast '(a)) => nil (butlast nil) => nilThe name is from the phrase "all elements but the last".
Examples: (setq foo '(a b c d)) (nbutlast foo) => (a b c) foo => (a b c) (nbutlast '(a)) => nil
Example: (firstn 2 '(a b c d)) => (a b) (firstn 0 '(a b c d)) => nil (firstn 6 '(a b c d)) => (a b c d nil nil)
Examples: (setq x '(a b c d e)) (setq y (cdddr x)) => (d e) (ldiff x y) => (a b c) but (ldiff '(a b c d) '(c d)) => (a b c d) since the sublist was not eq to any part of the list.
Example: (setq g '(a b c)) (rplaca (cdr g) 'd) => (d c) Now g => (a d c)
Example: (setq x '(a b c)) (rplacd x 'd) => (a . d) Now x => (a . d)Note to Maclisp users: rplacd should not be used to set the property list of a symbol, although there is a compatibility mode in which it will work. See car (LINK:(car-fun)). The right way to set a property list is with setplist (see LINK:(setplist-fun)). 'findex "setplist"
Example: (subst 'Tempest 'Hurricane '(Shakespeare wrote (The Hurricane))) => (Shakespeare wrote (The Tempest))subst could have been defined by:
(defun subst (new old s-exp) (cond ((equal s-exp old) new) ;if item eq to old, replace. ((atom s-exp) s-exp) ;if no substructure, return arg. ((cons (subst new old (car s-exp)) ;otherwise recurse. (subst new old (cdr s-exp))))))Note that this function is not "destructive"; that is, it does not change the car or cdr of any already-existing list structure.
(defun nsubst (new old s-exp) (cond ((eq s-exp old) new) ;If item eq to old, replace. ((atom s-exp) s-exp) ;If no substructure, return arg. (t ;; Otherwise, recurse. (rplaca s-exp (nsubst new old (car s-exp))) (rplacd s-exp (nsubst new old (cdr s-exp))) s-exp)))
Example: (sublis '((x . 100) (z . zprime)) '(plus x (minus g z x p) 4)) => (plus 100 (minus g zprime 100 p) 4)
There are functions to add (cons ), remove (delete , delq , del , del-if , del-if-not , remove , remq , rem , rem-if , rem-if-not ), and search for (member , memq , mem ) items in a list. Set union, intersection, and difference functions are easily written using these.
Association lists are very commonly used. An association list is a list of conses. The car of each cons is a "key" and the cdr is a "datum", or a list of associated data. The functions assoc , assq , ass , memass , and rassoc may be used to retrieve the data, given the key. Structured records can be stored as association lists or as stereotyped cons-structures where each element of the structure has a certain car-cdr path associated with it. However, these are better implemented using structure macros (see this link). Simple list-structure is very convenient, but may not be efficient enough for large data bases because it takes a long time to search a long list. Lisp Machine lisp includes a hashing function (sxhash ) which aids in the construction of more efficient, hairier structures.
Examples: (memq 'a '(1 2 3 4)) => nil (memq 'a '(g (x y) c a d e a f)) => (a d e a f)Note that the value returned by memq is eq to the portion of the list beginning with a . Thus rplaca on the result of memq may be used, if you first check to make sure memq did not return nil .
Example: (*catch 'lose (rplaca (or (memq x z) (*throw 'lose nil)) y) )memq could have been defined by:
(defun memq (item list) (cond ((atom list) nil) ((eq item (car list)) list) ((memq item (cdr list))) ))memq is hand-coded in microcode and therefore especially fast.
(defun member (item list) (cond ((null list) nil) ((equal item (car list)) list) ((member item (cdr list))) ))
(setq a (delq 'b a))rather than
(delq 'b a)The latter is not equivalent when the first element of the value of a is b . (delq item list n) is like (delq item list) except only the first n instances of item are deleted. n is allowed to be zero. If n is greater than the number of occurrences of item in the list, all occurrences of item in the list will be deleted.
Example: (delq 'a '(b a c (a b) d a e)) => (b c (a b) d e)delq could have been defined by:
(defun delq (item list &optional (n 7777777)) ;7777777 as infinity. (cond ((or (atom list) (zerop n)) list) ((eq item (car list)) (delq item (cdr list) (1- n))) ((rplacd list (delq item (cdr list) n)))))
Examples: (setq x '(a b c d e f)) (remq 'b x) => (a c d e f) x => (a b c d e f) (remq 'b '(a b c b a b) 2) => (a c a b)
sxhash computes a hash code of an S-expression, and returns it as a fixnum, which may be positive or negative. A property of sxhash is that (equal x y) implies (= (sxhash x) (sxhash y)) . The number returned by sxhash is some possibly large number in the range allowed by fixnums. It is guaranteed that: .break 1)SAIL sxhash for a symbol will always be positive. .break 2)SAIL sxhash of any particular expression will be constant in a particular implementation for all time, probably. .break 3)SAIL sxhash of any object of type random will be zero. .break 4)SAIL sxhash of a fixnum will = that fixnum. Here is an example of how to use sxhash in maintaining hash tables of S-expressions:
(defun knownp (x) ;look up x in the table (prog (i bkt) (setq i (plus 76 (remainder (sxhash x) 77))) ;The remainder should be reasonably randomized between ;-76 and 76, thus table size must be > 175 octal. (setq bkt (aref table i)) ;bkt is thus a list of all those expressions that hash ;into the same number as does x. (return (memq x bkt))))To write an "intern" for S-expressions, one could
(defun sintern (x) (prog (bkt i tem) (setq bkt (aref table (setq i (+ 2n-2 (SAIL\ (sxhash x) 2n-1))))) ;2n-1 and 2n-2 stand for a power of 2 minus one and ;minus two respectively. This is a good choice to ;randomize the result of the remainder operation. (return (cond ((setq tem (memq x bkt)) (car tem)) (t (aset (cons x bkt) table i) x)))))
(assq item alist) looks up item in the association list (list of conses) alist . The value is the first cons whose car is eq to x , or nil if there is none such.
Examples: (assq 'r '((a . b) (c . d) (r . x) (s . y) (r . z))) => (r . x) (assq 'fooo '((foo . bar) (zoo . goo))) => nil (assq 'b '((a b c) (b c d) (x y z))) => (b c d)It is okay to rplacd the result of assq as long as it is not nil , if your intention is to "update" the "table" that was assq 's second argument.
Example: (setq values '((x . 100) (y . 200) (z . 50))) (assq 'y values) => (y . 200) (rplacd (assq 'y values) 201) (assq 'y values) => (y . 201) nowA typical trick is to say (cdr (assq x y)) . Assuming the cdr of nil is guaranteed to be nil , this yields nil if no pair is found (or if a pair is found whose cdr is nil .) assq could have been defined by:
(defun assq (item list) (cond ((null list) nil) ((eq item (caar list)) (car list)) ((assq item (cdr list))) ))
Example: (assoc '(a b) '((x . y) ((a b) . 7) ((c . d) .e))) => ((a b) . 7)assoc could have been defined by:
(defun assoc (item list) (cond ((null list) nil) ((equal item (caar list)) (car list)) ((assoc item (cdr list))) ))
(defun rassoc (item in-list) (do l in-list (cdr l) (null l) (and (equal item (cdar l)) (return (car l)))))
(defun sassq (item alist fcn) (or (assq item alist) (apply fcn nil)))sassq and sassoc (see below) are of limited use. These are primarily leftovers from Lisp 1.5.
(defun sassoc (item alist fcn) (or (assoc item alist) (apply fcn nil)))
Example: (pairlis '(beef clams kitty) '(roast fried yu-shiang)) => ((beef . roast) (clams . fried) (kitty . yu-shiang))
Examples: (find-position-in-list 'a '(a b c)) => 0 (find-position-in-list 'c '(a b c)) => 2 (find-position-in-list 'e '(a b c)) => nil
[The stuff in FD.SYM will get moved here, leaving a pointer behind, and will be generalized for disembodied property lists and made to clarify the distinction between a plist and a paired list.]
A hash table is a Lisp object that works something like a property list. Each hash table has a set of entries , each of which associates a particular key with a particular value . The basic functions that deal with hash tables can create entries, delete entries, and find the value that is associated with a given key. Finding the value is very fast even if there are many entries, because hashing is used; this is an important advantage of hash tables over property lists. A given hash table can only associate one value with a given key ; if you try to add a second value it will replace the first. Hash tables are created with the function make-hash-table , which takes various options. New entries are added to hash tables with the puthash function. To look up a key and find the associated value, the gethash function is used. To remove an entry, use remhash . Here is a simple example.
(setq a (make-hash-table)) (puthash 'color 'brown a) (puthash 'name 'fred a) (gethash 'color a) => brown (gethash 'name a) => fredIn this example, the symbols color and name are being used as keys, and the symbols brown and fred are being used as the associated values. The hash table has two items in it, one of which associates from color to brown , and the other of which associates from name to fred . Keys do not have to be symbols; they can be any Lisp object. Likewise values can be any Lisp object. The Lisp function eq is used to compare keys, rather than equal . This means that keys are really objects, but it means that it is not reasonable to use numbers other than fixnums as keys. Hash tables are properly interfaced to the relocating garbage collector so that garbage collection will have no perceptible effect on the functionality of hash tables. When a hash table is first created, it has a size , which is the maximum number of entries it can hold. Usually the actual capacity of the table is somewhat less, since the hashing is not perfectly collision-free. With the maximum possible bad luck, the capacity could be very much less, but this rarely happens. If so many entries are added that the capacity is exceeded, the hash table will automatically grow, and the entries will be rehashed (new hash values will be recomputed, and everything will be rearranged so that the fast hash lookup still works). This is transparent to the caller; it all happens automatically. If the calling program is using multiprocessing, it must be careful to make sure that there are never two processes both referencing the hash table at the same time. There is no locking built into hash tables; if you have two processes that both want to reference the same hash table, you must arrange mutual exclusion yourself by using a lock or some other means. Don't worry about this if you don't use multiprocessing; but if you do use multiprocessing, you will have a lot of trouble if you don't understand this.
:size | Set the initial size of the hash table, in entries, as a fixnum. The default is 100 (octal). The actual size is rounded up from the size you specify to the next "good" size. You won't necessarily be able to store this many entries into the table before it overflows and becomes bigger; but except in the case of extreme bad luck you will be able to store almost this many. | |
:area | Specify the area in which the hash table should be created. This is just like the first argument to make-array (see LINK:(make-array-fun)). Defaults to nil (i.e. default-cons-area ). | |
:rehash-function | ||
Specify the function to be used for rehashing when the table becomes full. Defaults to the internal rehashing function that does the usual thing. If you want to write your own rehashing function, you will have to understand all the internals of how hash tables work. These internals are not documented here, as the best way to learn them is to read the source code. | ||
:rehash-size | Specifies how much to increase the size of the hash table when it becomes full. This can be a fixnum which is the number of entries to add, or it can be a flonum which is the ratio of the new size to the old size. The default is 1.3 , which causes the table to be made 30% bigger each time it has to grow. |
Several functions are provided for sorting arrays and lists. These functions use algorithms which always terminate no matter what sorting predicate is used, provided only that the predicate always terminates. The array sort is not necessarily stable ; that is, equal items may not stay in their original order. However the list sort is stable. After sorting, the argument (be it list or array) is rearranged internally so as to be completely ordered. In the case of an array argument, this is accomplished by permuting the elements of the array, while in the list case, the list is reordered by rplacd 's in the same manner as nreverse . Thus if the argument should not be clobbered, the user must sort a copy of the argument, obtainable by fillarray or append , as appropriate. Should the comparison predicate cause an error, such as a wrong type argument error, the state of the list or array being sorted is undefined. However, if the error is corrected the sort will, of course, proceed correctly. The sorting package is smart about cdr-coded lists.
Example: (defun mostcar (x) (cond ((symbolp x) x) ((mostcar (car x))))) (sort 'fooarray (function (lambda (x y) (alphalessp (mostcar x) (mostcar y)))))If fooarray contained these items before the sort:
(Tokens (The lion sleeps tonight)) (Carpenters (Close to you)) ((Rolling Stones) (Brown sugar)) ((Beach Boys) (I get around)) (Beatles (I want to hold your hand))then after the sort fooarray would contain:
((Beach Boys) (I get around)) (Beatles (I want to hold your hand)) (Carpenters (Close to you)) ((Rolling Stones) (Brown sugar)) (Tokens (The lion sleeps tonight))