TDDA23: Lisp and Artificial Intelligence

Elementary Lisp Syntax and Functions


Syntactic conventions

Symbolic expressions (S-expressions) are parenthesized expressions constructed recursively from symbols, strings, and numbers. Strings are written enclosed by double quotes (") and without any double quote inside. Numbers can be integers (e.g. 14) and real (e.g. 14.2).

Symbols are written using letters and digits. Some special characters are also allowed in symbols, for example +, -, and *. The following characters are not allowed in symbols:

   (  )  "  '  ,  \  #
One should be careful with other special symbols as well, and check that they work before using them in symbols.

Many Lisp systems are designed so that symbols only use capital letters and not small letters internally in the system, but allow both capital and small letters in input. They are converted from small to capital in input, and appear as capital in output. However there are also Lisp systems that distinguish capital and small letters throughout.

All of the above conventions can be bypassed using escape characters or other constructs. For example, it is possible to include a double quote character in a string by preceding it with a backslash (\).

The following are some important abbreviations:

The construct 'a is equivalent to (quote a)

The construct nil is equivalent to ()

The construct #'a is equivalent to (function a)

S-expressions are used as input to the Lisp system, and abbreviations can be used in that input. The output from the system consists of S-expressions, not using the abbreviations, but sometimes using special constructs for example for closures.

Semantic conventions

The symbols t and nil evaluate to themselves. The same holds for all numbers and strings.

In contexts where truth-values are assumed, or returned as values from functions, nil counts as 'false' and everything else counts as 'true'. Note that 0 and 1 do not have any relation to 'true' and 'false'.

Non-standard functions

Most Lisp functions are defined so that the evaluation of an expression
    (f a b c)
proceeds by first evaluating the arguments in order from left to right (a, then b, then c), and then applying the function (f) to the list of the evaluated arguments. However there is a small number of 'functions' that do not evaluate one or more of their arguments, in particular the following ones. (The expression "returns" means "has as value").
(quote a)           Returns the argument a

(function a)        Returns a closure for the argument a. The closure is
                    something that can be used as a function, and that may
                    contain values for some variables.

(if a b c)          Evaluates a, and then evaluates and returns either b or c
                    depending on whether the value of a is true or false
                    (i.e. non-nil or nil).

(defun f (x ...) b)  Defines f to be a function with (x ...) as the arguments
                    and with b as the expression to be evaluated to obtain
                    the value of a function for particular arguments. Does
                    not evaluate any of its arguments, and returns f as its 
                    value.

(setq a b)          Evaluates b, but not a. Then changes the value of a so
                    that it becomes the just-obtained value of b, and also
                    returns this as value from the setq-expression.

(setf (get a b) c)  Evaluates a, b, and c. Then resets the value of (get a b)
                    so that when (get a b) is evaluated in the sequel, the
                    just-obtained value of c is obtained.

The following function is used for convenience in this course, but is not part of the official definition of Lisp:
(put a b c)         Defined as (setf (get a b) c).
In addition to these, there are constructs for bindings and loops (let, prog, doloop and others) which will be described on a separate page. The above functions are sufficient for programming, together with the standard functions, and the other binding and loop constructs are for convenience.

Standard functions for lists and arbitrary S-expressions

(car x)             Returns the first element of the list x, or nil if the
                    argument is nil. Error if x is not a list or nil.

(cdr x)             Returns the rest of the list x after removing the first
                    element, or nil if the argument is nil. Error if x is not
                    a list or nil.

(cons x y)          Returns a list whose first element is x and whose rest
                    after the first element is y

(list x y ...)      Returns a list consisting of x, y, etc.

(equal x y)         Returns true (t) if x and y are equal S-expressions, 
                    otherwise false (nil).

Standard functions for numbers

All the following functions must have numbers as arguments, and return a number.
(+ x y ...)         The sum of the arguments.

(- x y)             The difference of the arguments

(* x y ...)         The product of the arguments

(/ x y)             The quotient of the arguments. If all the arguments are
                    integers or fractions then a fraction is obtained, in full
                    CommonLisp see below about fractions), otherwise a real 
                    number is obtained.

(= x y)             True (t) if x and y are equal, otherwise false (nil).
                    Note that = can only be used for numbers, otherwise use
                    the function equal. 

(< x y)             True if x is strictly less than y. - Similar for > etc.

Standard functions for strings

All the following functions must have strings as arguments, and return a string.
(concatenate 'string a b ...)    Returns the concatenation of the strings a, b,...
                    given as arguments.

Standard functions for type checking and conversion

(listp x)          True if the argument is a list, or nil.
 
(symbolp x)        True if the argument is a symbol, including nil.

(stringp x)        True if the argument is a string.

(numberp x)        True if the argument is a number.

(string x)         The argument is a symbol; returns the corresponding string.

(intern x)         The argument is a string; returns the corresponding symbol.

(prin1-to-string x)    The argument is an arbitrary S-expression. Returns a string
                   containing the parenthesized expression of the argument. For
                   example, (prin1-to-string '(a b)) returns the string
                   "(a b)", or "(A B)" in a system that only used capital letters.

(read-from-string x)   The converse of prin1-to-string. For example,
                    (read-from-string "(a b)") returns (a b).

Additional data structures

It is possible to form an S-expression cdr of which is not a list or nil. Such an expression is written as (a . b). For example, the value of
   (cdr '(alpha . beta))
is the symbol beta, and the value of
   (cons 'gamma 'delta)
is the S-expression (gamma . delta).

Full CommonLisp also allows fractions as a kind of numbers, so that for example the value of (/ 12 5) is the fraction 12/5, and the value of (+ (/ 12 5) 3) is 27/5.

Additional non-standard functions

(cond (c1 v1)(c2 v2) ... (cn vn))
                     Evaluates c1, c2, and so forth in turn until it finds
                     one whose value is true (i.e. non-nil). Then evaluates
                     and returns the corresponding vi. If no ci evaluates to
                     true, then returns nil. Often cn is chosen as t, so
                     that it becomes the 'else' clause. (Recall that t always
                     evaluates to itself).

Progn and implicit progn

The function progn is defined so that (progn a b c ... e) evaluates all its arguments and returns the value of the last argument. It is used when the arguments have side-effects, for example using setq, setf, or put, but also using input/output functions such as read or print (not described here).

Some of the non-standard functions described above allow 'implicit progn', that is, the effect of a progn in their argument structure. This applies in particular for defun and cond, so that for example (defun f (a) b c) defines a function with the same behavior as for (defun f (a)(progn b c)). Similarly,

   (cond (a b c d)
         (t e f) )
always returns the same value as
   (cond (a (progn b c d))
         (t (progn e f)) )

Evaluation and application

The following functions call the Lisp interpreter recursively. Notice that all of these are standard functions that first evaluate their arguments in the same sense as other standard functions do, and then the evaluation or application occurs after that.
(eval a)           Evaluates its (evaluated) argument and returns its value.

(funcall f a b ...)   Applies the function f to the argument list of a, b,...

(apply f a)        Requires a to be a list, and applies the function f to 
                   the arguments obtained as the successive elements of a.
Examples:
Input                                Obtained value

(eval '(cons '+ '(4 5)))             9

(apply #'+ (list 4 5))               9

(funcall #'+ 4 5)                    9

(funcall #'cons 'a '(b c))           (a b c)

(apply #'car '(((a))))               (a)
                                     because (((a))) is the list of arguments
                                     for car, so ((a)) is the argument for car,
                                     and then (a) is the value


Posted on 2005-09-06 as part of the CAISOR website. [Version history].