CS 470/570: Common Lisp for Schemers

Fall 1996


The major difference between Scheme and Common Lisp is that objects used as functions are evaluated differently from objects used as arguments. In a combination such as (F A), F is in functional position, and is typically the name of a function. A is in argument position, and is an evaluable expression of some kind. If you want to use a function as an argument, the prefix #' will be very useful. #'x is an abbreviation for (FUNCTION x), just as 'x is an abbreviation for (QUOTE x). When a function is used as an argument, it must be flagged this way: (FOO #'LIST) calls the function FOO with the function LIST as an argument. For FOO to do something with its argument, it must use FUNCALL:
    (DEFUN FOO (F)
       (FUNCALL F F))
(FOO #'LIST) calls LIST with itself as argument, and returns a list of one element, the LIST function itself. [This happens to print out something like this:
             (#<Compiled-Function LIST 5DEFE>)
a list of one element, the thing printed inside brackets #<...> .]

Common Lisp allows LAMBDA expressions, just as Scheme does, but they must be prefixed by #'. So given a procedure (COLLECT l pred) that collects all the elements of list l that satisfy pred:

   (defun collect (l pred)
      (cond ((null l) '())
	    ((funcall pred (car l))
	     (cons (car l) (collect (cdr l) pred)))
	    (t
	     (collect (cdr l) pred))))
we can collect all the numbers in a list that are smaller than 5 thus:
   (collect l #'(lambda (i) (< i 5)))

Predicates in Common Lisp do not end in question marks. Some predicates end in "P", and some have no distinguishing lexicography. EQ is used for comparing symbols; EQL compares symbols, characters, and numbers; while = compares numbers. (Note that (= 1 1.0) is T, while (eql 1 1.0) is NIL.) ATOM is used for checking if something is not a list. It may seem confusing to have several different equality testers, but then equality is a confusing relation.

The boolean values in Common lisp are NIL (false) and non-NIL (true). A standard non-NIL value is the symbol T. #t and #f do not exist. Note that the symbol NIL, the empty list, and false are all identically the same object in Common Lisp. This identity is an unfortunate legacy, and tasteful code should pretend that it does not obtain. Write '() when you mean the empty list, NIL when you mean falsehood, 'NIL when you mean the symbol NIL.

Common Lisp has the idea of "sequence," an abstract data type that includes strings, lists, and one-dimensional arrays (vectors). Many operations, such as LENGTH, are defined to operate on any sequence.

Some procedures take an indefinite number of arguments. LIST and + are good examples. See DEFUN below for how you can define procedures of this kind using &REST.

Procedures in Common Lisp can take keyword arguments, which are flagged by keywords beginning with ":"; the order of the arguments is unimportant. E.g., if CLUM is such a procedure, it might take two arguments positionally, followed by 15 keyword arguments, and be called like this:

   (CLUM (ARGUMENT 1) (ANOTHER ARGUMENT)
         :COLOR 'PURPLE
         :SIZE 'LARGE
         :REPETITIONS (+ N 1))
This feature is handy for functions that take a lot of mostly optional arguments. Many built-in functions take their optional arguments this way. Consult a real manual if you want to define a procedure that takes keyword arguments.


The rest of this manual is in alphabetical order.

(APPEND l1 ... lN): Create and return a list consisting of all the
    elements of l1, followed by all the elements of l2, through all
    the elements of lN.

(APPLY fcn a1 ... aN l): Call function <fcn> with arguments a1,...,aN, e1, ...,eK, where e1,...,eK are the elements of list l . For example, if I is a number and L is a list of numbers, (APPLY #'+ I L) returns the sum of I and the elements of L. N can be 0, of course.

(AREF array -subscripts-) refers to the given element of <array>. The first element along any dimension is number 0. Use with SETF to alter an array element.

Arithmetic: Common Lisp has all the mathematical functions you could want, including hyperbolic tangent on complex numbers.

(ASSOC x alist): Looks up object x in an "association list" <alist>. This is a table implemented as a list of the form ((ob1 e1) (ob2 e2) ...), i.e., a list of lists, where list I stands for a table entry with key obI. ASSOC finds and returns the entry for key x, or NIL if there is no such entry. ASSOC decides whether it's found the correct entry by testing it for equality with x using EQL. If you want to use another equality tester, provide keyword argument :TEST, as in (ASSOC '(FOO BAR) L :TEST #'EQUAL).

(CHAR-DOWNCASE c), (CHAR-UPCASE c): Return upper- and lower-case versions of alphabetic characters.

(CHAR-INT c): Convert a character to an integer in some coding scheme (usually ASCII).

(CHAR< c1 c2): Tests whether character c1 is "less than" c2, alphabetically. We also have CHAR>, CHAR<=, etc.

(COERCE x type): Generate a version of x of the given <type>. Most useful to convert one kind of sequence to another. E.g., (COERCE '(#\W #\E #\I #\R #D) 'STRING) => "WEIRD"

(CONCATENATE resulttype s1 ... sN): Create a new sequence by concatenating the elements of the given sequence. The new sequence is of type <resulttype>.

(COPY-SEQ s): Copy a sequence.

(COUNT x s): Count the number of occurrences of x in sequence s. Use EQL to test for equality.

(DEFSETF accessor setter): Tells Lisp that (SETF (<accessor> x) y) should be expanded into (<setter> x y).

(DEFUN name (-args-) -body-): Define function <name> with the given bound-variable arguments <args>. When the function is called, the arguments passed to it are evaluated and the <args> are bound to them. Then the <body> is evaluated. When the function returns, the bound variables are discarded and the value of the <body> is return.

In Common Lisp, argument specifications can have a more complicated syntax than in Scheme. The major enhancement is to allow a bound variable to be bound to a list of all the remaining arguments, by prefixing it with the keyword &REST. E.g., (DEFUN FRIBBLE (X &REST L) (CONS X (REVERSE L))) defines FRIBBLE so that (FRIBBLE 'WOW 'AROUND 'ME 'TURN)) evaluates to (WOW TURN ME AROUND). (DEFSTRUCT (strname [(:PRINT-FUNCTION printer)]) (slotname1 [default1]) (slotname2 [default2]) ...) Defines a structure type <strname>, a new data type whose instances have slots named <slotname1>, <slotname2>, .... To create a new instance, evaluate (MAKE-strname :slotname1 val1 :slotname2 val2 ...)

You can then access the slots using functions with names strname-slotname. (See examples below.)

The :PRINT-FUNCTION (optional) should be a function of three arguments: the instance to be printed, the stream to print it on, and the depth at which the object occurred in printing something else. (Don't worry about the third argument.) It should print some representation of the instance on the stream.

Example: (DEFSTRUCT (STUDENT (:PRINT-FUNCTION STUD-PRINTER)) (NAME) (CLASS) (MAJOR 'CS)) (DEFUN STUD-PRINTER (STUDENT STREAM D) (FORMAT STREAM "#<Student ~a>" (STUDENT-NAME STUDENT)))

(SETF JOE-COLLEGE (MAKE-STUDENT :NAME "Joe College" :CLASS 96)) creates an object that prints out as #<Student Joe College> and (STUDENT-MAJOR JOE-COLLEGE) will be CS. You can delay Joe's graduation by evaluating (SETF (STUDENT-CLASS JOE-COLLEGE) 99).

(DEFVAR var [value]): Define a global variable <var>. An optional value may be supplied.

(DO ((v_1 i_1 n_1) ... (v_k i_k n_k)) (test result) -body-) Evaluate i_1,...,i_k. Bind v_1,...,v_k to the values. Evaluate <test>. If false, execute <body>. Then evaluate all the n_j's, and then reset all the v_j's to the values. Evaluate <test> again. If false, repeat. The first time <test> evaluates to true, evaluate and return <result>.

(DOLIST (v l [result]) -body-): Bind variable v to successive elements of list l, and execute body for each. Return result if supplied. E.g., REVERSE could have been defined as (DEFUN REVERSE (L) (LET ((R '())) (DOLIST (X L R) (SETF R (CONS X R)) )))

(DOTIMES (v N [result]) -body-): Bind variable v to integers from 1 to N, executing body for each. Return result if supplied.

(ELT s i): Return the i'th element of sequence s. The first element is number 0. Use with SETF to alter the contents of a string.

(EQUAL x y): Test whether x and y "look the same," that is, if they are EQL or are structures (lists or strings) whose elements are EQUAL.

(EQUALP x y): Yet another equality tester, that behaves like EQUAL except that it recurses through the elements of arrays as well as lists and strings. E.g., If A1 = #(1 2 3), and A2 = #(1 2 3), then (EQUAL A1 A2) => NIL, but (EQUALP A1 A2) => T.

(FIND x s): If element x occurs in sequence s, return it, else NIL. Use EQL to test x against elements of s. (Or supply :TEST keyword argument.)

(FORMAT stream controlstring -args-): Print the args on output stream <stream> as dictated by <controlstring>. The characters of the control string are printed, interspersed with values of args, printed according to "format directives," which are flagged with a tilde (~). ~s means "print as symbolic expression" -- i.e., as read ~a means "print as ascii string" -- i.e., without quotes ~% means "print a newline" ~<newline><whitespace> is ignored T may be supplied instead of the stream, when it means standard output. (FORMAT *STANDARD-OUTPUT* "Three things: ~s, ~s~% ~s~%" I J K) prints (if I,J, and K have values 1, 2, and FOO): Three things: 1 2 FOO

(FUNCALL fcn a1 ... aN): Call <fcn> on the given arguments.

(GET symbol prop): Every symbol has a "property list" that records a table of associations to it. GET retrieves such an association. Use SETF to change it.

(INT-CHAR i): Convert an integer to a character. The inverse of CHAR-INT.

(LABELS ((fcn1 (-args-1-) -body-1-) (fcn2 (-args-2-) -body-2-) ...) -body-) Defines several local functions, with names <fcn1>, <fcn2>,..., and then evaluates <body>. When <body> is done, any previous definitions of <fcnI> will be restored. Unlike Scheme's DEFINE, Common Lisp's DEFUN will not define local functions when used inside another DEFUN; use LABELS instead. The square-root routine below is adapted from a Scheme version from the book by Abelson and Sussman (p. 28):

(defun sqrt (x) (labels ((good-enough? (guess) (< (abs (- (square guess) x)) .001)) (improve (guess) (average guess (/ x guess))) (sqrt-iter (guess) (if (good-enough? guess x) guess (sqrt-iter (improve guess))))) (sqrt-iter 1))) (It is not necessary to use this code -- sqrt is already defined in Common Lisp.)

(LENGTH s): Number of elements in a sequence.

(LOAD filename): Loads the file with the given name (a string), evaluating everything in it. Usually a file contains mostly DEFUNs, but any evaluable expression is allowed.

(LOOP -body-): Do <body> repeatedly. Exit using (RETURN val). E.g., FIND could have been defined thus: (DEFUN FIND (X L) (LOOP (IF (NULL L) (RETURN NIL)) (IF (EQL (CAR L) X) (RETURN (CAR L))) (SETF L (CDR L))))

(MAKE-ARRAY dimensions [:INITIAL-ELEMENT x] [:INITIAL-CONTENTS c]) Create and return an array with the given <dimensions>. The <dimensions> must evaluate to either a single integer or a list of integers. If :INITIAL-ELEMENT x is provided, then the array is filled with x's. If :INITIAL-CONTENTS c is provided, then c must be a sequence of values to store in the array. (This gets complicated if there is more than one dimension.) E.g., (MAKE-ARRAY '(3 4) :INITIAL-ELEMENT 5) creates a 3-by-4 array of 5's.

(MAKE-STRING size [:INITIAL-ELEMENT char]): Create and return a new string, whose elements are all equal to the specified char, if supplied, or left unspecified.

(MAP resulttype fcn s1 ... sN): Create a new sequence of type <resulttype> by applying fcn to the first elements of s1,...,sN, then the second elements, etc., and putting the results together in order. (MAP 'STRING #'CHAR-UPCASE '(#\w #\e #\i #\r #\d)) => "WEIRD"

(MAPCAR fcn l1 ... lN): Equivalent to (MAP 'LIST fcn l1 ... lN).

(MEMBER x l): If x does not occur in l, return NIL. Otherwise, return the tail of the list beginning with x. E.g., (MEMBER 5 '(1 3 5 7 5)) => (5 7 5)

*PRINT-ARRAY*,*PRINT-LENGTH*,*PRINT-LEVEL*,*PRINT-PRETTY*: These are not functions, but global variables. If *PRINT-ARRAY* is T, then vectors are printed by printing their elements between "#(" and ")" . It's normally NIL. (By the way, vectors can always be read this way.) *PRINT-LENGTH* and *PRINT-LEVEL* control how much (i.e., the max length and max depth) of a large list structure will be printed. If *PRINT-PRETTY* is T, then big lists are printed with indentation, the way you should lay them out.

(PROG1 e1 ... eN) (PROGN e1 ... eN): Each of these evaluates each of its arguments. PROG1 returns the value of the first; PROGN, of the last. PROGN is useful when a sequence of statements is required, as in (IF (some test) (PROGN things to do if true) (PROGN things to do if false))

(RANDOM x): Return a random number between 0 and x (not including x).

(REMOVE x s): Create a new sequence with every occurrence of x removed. EQL is used to test for equality with x. You can override this by supplying a :TEST keyword argument.

(REVERSE s): Create a new sequence that is the reverse of s.

(SETF form x):

Change <form> so that its value is <x>. The <form> can be a variable, or an array reference, or any other changeable expression, including (ELT ...).

(SORT s pred): Sort s, using <pred> to compare elements. <pred> should be a function of two arguments that returns a boolean value, and behaves like a total order. E.g., (SORT "ZAYB" #'CHAR<) returns "ABYZ". Important: SORT alters its argument. If you want to keep an unsorted copy, use (SORT (COPY-SEQ ...) ...).

(SUBSEQ seq start [end]): Return a subsequence of <seq>, from element <start> to element <end>. If <end> is missing, to end of sequence.

(VECTOR e1 ... eN): Make a vector (one-dimensional array) of the given N elements. Analogous to (LIST e1 ... eN), which makes a list of the given N elements.