LISP
Lecture Notes
LISP
• LISP was the first functional programming language.
• With the exception of the first version all LISP dialects
include imperative language features such as, imperative
style variables, assignment statements, and iteration.
Symbolic Expressions, the Syntactic Basis
of LISP
• The syntactic elements of the LISP programming language are
symbolic expressions.
• Both programs and data are represented as s-expressions. An s-
expression may be either an atom or a list.
• Symbolic atoms are composed of letters numbers and certain non-
alphanumeric characters (* - + $ % ^ &_ > < )
• A list is a sequence of either atoms or other lists separated by blanks
and enclosed in parentheses.
Examples
• ‘(A B C D)
• ‘(A (B C) D (E (F G)))
(function_name arg_1 … arg_n)
Example
( + 5 7 )
evaluates to 12.
Examples
• ‘(1 2 3 4)
• ‘(likes bill ?X)
• (- (+ 3 4) 7)
• (=(+ 2 3) 5)
• (list 1 2 3 4)
• (nth 0(list a b c d))
0
t
(1 2 3 4)
a
Concepts Behind LISP
• From this emerged a universal LISP function that could
evaluate any other function in LISP.
• The first requirement for the universal LISP function was a
notation that allowed functions to be expressed in the same
way data was expressed.
• Function calls were specified in a prefix list form called
Cambridge Polish
• In evaluating a function LISP first evaluates its arguments
and then applies the function indicated by the first element
of the expression to the results of these evaluations. For
example in evaluating the expression
(+ (* 2 3) (* 3 5))
• LISP first evaluates the arguments (* 2 3) and (* 3 5).
These results are then passed to the top level addition
which is evaluated, returning 21.
Definition
S-Expression
An s-expression is defined recursively:
1. An atom is an s-expression.
2. If s1, s2,...,sn are s-expressions,
then so is the list (s1, s2,...,sn).
Evaluating an s-expression
• A list is a non-atomic expression.
• In evaluating an s-expression:
– If the s-expression is a number, return the value of the
number.
– If the s-expression is an atomic symbol, return the value
bound to that symbol; if it is not bound then it is an
error.
– If the s-expression is a list, evaluate the second through
the last arguments and apply the function indicated by
the first argument to the result.
Control of LISP Evaluation: quote and eval
The purpose of the quote is to prevent evaluation of s-
expression that should be treated as data rather than an
evaluable form.
(quote(a b c ))
(quote(+1 3))
(list(+1 2) (+ 3 4))
(list ‘(+ 1 2) ‘(+ 3 4))
(>(* 5 6) (+ 4 5))
(‘(a b c )) (a b c)
(‘(+ 1 3)) (+ 1 3 )
(3 7)
((+ 1 2) (+ 3 4))
t
eval is a complement to quote.
(quote(+ 2 3)) (+ 2 3)
(eval(quote(+ 2 3))) 5
Programming in LISP: Creating New Functions
LISP supports a large number of built in functions
– Arithmetic functions supporting both integers and real numbers.
– Program control functions
– List manipulation and other data structuring functions.
– Input/Output functions
– Forms for the control of function evaluation
– Functions for the control of the environment and operating system.
(defun square(x)
(* x x))
>(square 5) ; causes 5 to be bound to x
25
(defun <function name> (<formal parameters>)
(<function body) )
(defun hypotenuse(x y)
(sqrt (+ (square(x)) (square(y))))
Program Control in LISP: Conditionals
and Predicates
cond takes as arguments a number of condition - action pairs.
(cond (<condition1> <action1>)
(<condition2> <action2>)
................
(<conditionn> <actionn>) )
(defun absolute-value(x)
(cond ((< x 0) (-x))
((> = x 0) (x))))
(defun absolute-value(x)
(cond ((< x 0) (-x))
(t x)))
If clause
if takes three arguments
(defun absolute-value(x)
(if (< x 0 ) (-x) x ))
Predicates
A predicate is a LISP function that returns nil to indicate ‘false’ and
anything other than nil to indicate ‘true’.
> (= 9 (+ 4 5))
t
>(oddp 4)
nil
Examples to arithmetic predicates are: <, >, =, oddp, evenp, zerop, plusp,
minusp.
>(member 3 ‘(1 2 3 4 5))
(3 4 5)
All Boolean functions are short circuit in Common LISP. They return a value as soon as the result is determined.
>(and(t t nil t))
nil
>(or( t nil t t))
t
Lists as Recursive Structures
The basic functions for accessing the components of a list are
car and cdr.
car (first) - Takes a list as its argument and returns the
first element of the list.
cdr (rest) - Takes a list as its argument and returns the
list with the first argument removed.
>(car ’(a b c ))
a
>(cdr ’(a b c))
(b c)
>(car(cdr ’(a b c d)))
b
A recursive approach to manipulate list structures to perform
an operation on each of the elements of a list
1. If the list is empty quit
2. Perform the operation on the first element of the list and
recur on the remainder of the list.
Common LISP predicates for list processing are
member : Determines whether an s-expression
is a member of a list.
length : Determines the length of a list.
Example:
Define ‘my-member’ which takes an atom and a list
as arguments and returns nil if the atom is not
present in the list, otherwise returns the portion of
the list containing the atom as the first element.
(defun my-member(element list)
(cond((null list) nil)
((equal element(car list)) list)
(t (my-member element (cdr list))))
>(my-member 4 ‘(1 2 3 4 5 6))
(4 5 6)
(defun my-length(list)
(cond((null list) 0)
(t (+ (my-length (cdr list) 1)))))
cons is a basic list constructor
(cons ’A ’(L I S)) (A L I S)
(cons ’A ’B) (AB)
(cons ’(A) ’(L I S)) ((A) L I S)
car and cdr tear lists apart and drive the recursion ; cons
selectively constructs the result as the recursion unwinds.
Recursion is used to scan the list element by element, as the
recursion unwinds the cons function reassembles the solution.
If cons is called with two lists as arguments it makes the
first of these a new first element of the second list,
whereas append returns a list whose elements are the
elements of the two arguments:
>(cons ’(1 2) ‘(4 5 6))
((1 2) 4 5 6))
>(append ’(1 2) ‘(4 5 6))
(1 2 4 5 6)