Title: COSC3306: Programming Paradigms Lecture 11: Applicative Programming with Lisp
1COSC3306Programming ParadigmsLecture 11
ApplicativeProgramming with Lisp
- Haibin Zhu, Ph.D.
- Computer Science
- Nipissing University (C) 2003
2Versions of LISP
- Lisp is an old language with many variants
- Lisp is alive and well today
- Most modern versions are based on Common Lisp
- LispWorks is based on Common Lisp
- Scheme is one of the major variants
- The essentials havent changed much
3Recursion
- Recursion is essential in Lisp
- A recursive definition is a definition in which
- certain things are specified as belonging to the
category being defined, and - a rule or rules are given for building new things
in the category from other things already known
to be in the category.
4Informal Syntax
- An atom is either an integer or an identifier.
- A list is a left parenthesis, followed by zero or
more S-expressions, followed by a right
parenthesis. - An S-expression is an atom or a list.
- Example (A (B 3) (C) ( ( ) ) )
5Formal Syntax (approximate)
- ltS-expressiongt ltatomgt ltlistgt
- ltatomgt ltnumbergt ltidentifiergt
- ltlistgt ( ltS-expressionsgt )
- ltS-expressions gt ltemptygt
ltS-expressions gt ltS-expressiongt - ltnumbergt ltdigitgt ltnumbergt ltdigitgt
- ltidentifiergt string of printable characters,
not including parentheses
6LISP facilities
- LISP facilities
- A method for storing data,
- A set of built-in functions,
- A set of functional forms, and
- A set of operators.
- Two features
- Each data object carries a run-time descriptor
giving its type and other attributes. - If a data object has components (is a structured
data object), the components are never
represented directly as part of the data object
instead a pointer to the component data object is
used.
7Data Objects
- Every LISP data object, whether a program or
data, is either an atom or a cons. An atom is an
object that is indivisible in nature and takes
two forms - A literal atom (symbol), which is a string
beginning with a letter, and - A numeric atom (number), which is a number used
for integer and real arithmetic operations
numbers are their own values.
8T and NIL
- NIL is the name of the empty list
- As a test, NIL means false
- T is usually used to mean true, but
- anything that isnt NIL is true
- NIL is both an atom and a list
- its defined this way, so just accept it
9Function calls and data
- A function call is written as a list
- the first element is the name of the function
- remaining elements are the arguments
- Example (F A B)
- calls function F with arguments A and B
- Data is written as atoms or lists
- Example (F A B) is a list of three elements
- Do you see a problem here?
10Quoting
- Is (F A B) a call to F, or is it just data?
- All literal data must be quoted (atoms, too)
- (QUOTE (F A B)) is the list (F A B)
- QUOTE is a special form
- The arguments to a special form are not evaluated
- '(F A B) is another way to quote data
- There is just one single quote at the beginning
- It quotes one S-expression
11Basic Functions
- CAR returns the head of a list
- CDR returns the tail of a list
- CONS inserts a new head into a list
- EQ compares two atoms for equality
- ATOM tests if its argument is an atom
12Figure 13.1 Memory representation of (cons A B)
13Figure 13.2 Memory representation of (cons A
(cons CAR NIL))
14Figure 13.3 Memory representation of (cons A
(cons B C))
15Figure 13.4 A representation of list (A (BC) D)
16Figure 13.5 A representation of list ((AB) (C )
(DF))
17Figure 13.6 Cell diagram representation of list
(a b c)
18Figure 13.7 Cell diagram representation of list
(a b) (c ) (d f))
19Figure 13.9 Scheme evaluation of expression (
( - 5 2) ( 2 3))
20Other useful Functions
- (NULL S) tests if S is the empty list
- (LISTP S) tests if S is a list
- LIST makes a list of its (evaluated) arguments
- (LIST 'A '(B C) 'D) returns (A (B C) D)
- (LIST (CDR '(A B)) 'C) returns ((B) C)
- APPEND concatenates two lists
- (APPEND '(A B) '((X) Y) ) returns (A B (X) Y)
21CAR
- The CAR of a list is the first thing in the list
- CAR is only defined for nonempty lists
If L is Then (CAR L) is (A B C) A
( (X Y) Z) (X Y)
( ( ) ( ) ) ( )
( ) undefined
22CDR
- The CDR of a list is what's left when you remove
the CAR - CDR is only defined for nonempty lists
- The CDR of a list is always a list
23CDR examples
If L is Then (CDR L) is (A B C) (B C)
( (X Y) Z) (Z)
(X) ( )
( ( ) ( ) ) ( ( ) )
( ) undefined
24CONS
- CONS takes two arguments
- The first argument can be any S-expression
- The second argument should be a list
- The result is a new list whose CAR is the first
argument and whose CDR is the second - Just move one parenthesis to get the result
25CONS examples
- CONS puts together what CAR and CDR take apart
L (CAR L) (CDR L) (CONS (CAR L)
(CDR L)) (A B C) A (B C) (A B
C)
( (X Y) Z) (X Y) (Z) ( (X Y) Z)
(X) X ( ) (X)
( ( ) ( ) ) ( ) ( ( ) ) ( ( ) ( ) )
( ) undefined undefined undefined
26Dotted Pairs
- The second argument to CONS should be a list
- If it isn't, you get a dotted pair
- CONS of A and B is (A . B)
- If you get a dotted pair, it's because you gave
CONS an atom as a second argument
27EQ
- EQ tests whether two atoms are equal
- Integers are a kind of atom
- EQ is undefined for lists
- it might work for lists, it might not
- but it won't give you an error message
- As with any predicate, EQ returns either NIL or
something that isn't NIL
28ATOM
- ATOM takes any S-expression as an argument
- ATOM returns "true" if the argument you gave it
is an atom - As with any predicate, ATOM returns either NIL or
something that isn't NIL
29COND
- COND implements the if...then...elseif...then...e
lseif...then... control structure - The arguments to a function are evaluated before
the function is called - This isn't what you want for COND
- COND is a special form
30To be continued
31Special forms
- A special form is like a function, but it
evaluates the arguments as it needs them - COND, QUOTE and DEFUN are special forms
- You can define your own special forms
32Form of the COND
(COND (condition1 result1 )
(condition2 result2 ) . . . (T
resultN ) )
33Defining Functions
- (DEFUN function_name parameter_list
function_body ) - Example Test if the argument is the empty list
- (DEFUN NULL (X) (COND (X
NIL) (T T) ) )
34Example MEMBER
- As an example we define MEMBER, which tests
whether an atom is in a list of atoms - (DEFUN MEMBER (A LAT) (COND
((NULL LAT) NIL) ((EQ A (CAR LAT))
T) (T (MEMBER A (CDR LAT))) ) ) - MEMBER is typically a built-in function
35Rules for Recursion
- Handle the base (simplest) cases first
- Recur only with a simpler case
- Simpler more like the base case
- Dont alter global variables (you cant anyway
with the Lisp functions Ive told you about) - Dont look down into the recursion
36Guidelines for Lisp Functions
- Unless the function is trivial, start with COND.
- Handle the base case first.
- Avoid having more than one base case.
- The base case is usually testing for NULL.
- Do something with the CAR and recur with the CDR.
37Example UNION
(DEFUN UNION (SET1 SET2) (COND
((NULL SET1) SET2) ((MEMBER (CAR SET1)
SET2) (UNION (CDR SET1) SET2) )
(T (CONS (CAR SET1) (UNION (CDR
SET1) SET2) )) ) )
38Still more useful Functions
- (LENGTH L) returns the length of list L
- (RANDOM N) , where N is an integer, returns a
random integer gt 0 and lt N.
39How EQUAL could be defined
- (defun equal (x y)
- this is how equal could be defined
- (cond ((numberp x) ( x y))
- ((atom x) (eq x y))
- ((atom y) nil)
- ((equal (car x) (car y))
- (equal (cdr x) (cdr y)))))
40Lambda expression
- A lambda expression has the form
- (lambda ?argument-list?
- ?function-body? )
- In other words, a lambda expression is somewhat
like defun, except that it defines an unnamed
function, or it allows the user to define a
function with no name. - For example,
- ((lambda (x y) ( x y)) 2 3)
- binds x and y to 2 and 3, respectively, and
applies , giving 5 as the returned value of this
definition. Even though LISP can be used as a
functional programming language, few applications
written in LISP are purely applicative. Any
realistic LISP program makes heavy use of
non-applicative features to achieve a reasonable
level of efficiency.
41The set function
- The set function is simply an assignment
statement and a value of a symbol can be assigned
with the general form - (set symbol expression)
- in which the expression is assigned to symbol and
symbol evaluates to that value until set is
applied again. Examine the following examples
about set function. - eval? (set X (A B C) )
- (A B C)
- eval? (set B 3)
- 3
- eval?(set Y A)
- A
- eval? Y
- A
- eval? (set Z X)
- (A B C)
42The special form let
- The special form let is a function that provides
a way of introducing temporary variables or
binding local variables. Temporary variables can
serve the result of a computation. The general
form of let is - (let ( (variable1 value1)
- (variable2 value2)
-
- (variablen valuen) )
- body)
- in which variable1, variable2, , variablen, are
symbols (let does not evaluate them) that will be
used as names on introduced variables. They can
be referred to by any code that appears in the
body form. When let is invoked, each of value1,
value2, , valuen is evaluated in turn. When they
all have been evaluated, the new variables are
given their values. Examine the following
examples about let function. - eval? (let ((A 3)) (cons A (let ((A 4)) A)
) ) - (3 4)
- eval? (let ((A 3)) (let ((A 4) (B A) )
(cons A B) ) ) - (4 3)
43The special form prog
- (progn expression1, expression2, , expressionn)
- (progn (set x 3) (set y 4) (print ( x y)))
44Some simple list processing examples
- (defun member (x l)
- (cond ((atom l) nil)
- ((equal x (car l)) (cdr l))
- (T (member x (cdr l))))
- (defun append (l1 l2)
- (if (null l1)
- l2
- (cons (car l1) (append (cdr l1) l2))))
-
45Variations on reverse
- either of these does O(n2) cons operations
- (defun reverse (l)
- (if (null l)
- nil
- (append (reverse (cdr l)) (list
(car l))))) - (defun reverse (l)
- (and l (append (reverse (cdr l)) (list
(car l)))))
46Flatten
- (defun flatten (l)
- (cond ((null l) nil) empty list do
nothing - ((atom (car l))
- cons an atom onto flattend cdr
- (cons (car l) (flatten (cdr l))))
- otherwise flatten head tail and
append results - (t (append (flatten (car l))
(flatten (cdr l))))))
47Higher order functions
- (defun mapcar (f l)
- (if (null l)
- nil
- (cons (apply f (list (car l)))
- (mapcar f (cdr l)))))
-
48Examples
- http//sandbox.mc.edu/bennet/cs404/doc/lisp.html
- http//www.cs.ualberta.ca/tommy/ta/325/lisp_examp
les.html - http//www.notam02.no/internt/cm-sys/cm-1.4/doc/ex
amples/
49Common Lisp
50Why Common Lisp?
- Common Lisp is a high-level, dynamical,
extensible language, suitable for symbolic and
numerical processing - Modern Common Lisp implementations provide
compilers, automatic memory management,
multithreading, powerful debuggers - A large number of legacy AI systems written in
Lisp exist.
51Input and Output
- Print is the most primitive output function
- gt (print (list 'foo 'bar))
- (FOO BAR)
- (FOO BAR)
- The most general output function in CL is format
which takes two or more arguments - the first indicates where the input is to be
printed, - the second is a string template,
- the remaining arguments are objects whose printed
representations are to be inserted into the
template - gt (format t A plus A equals A. 2 3 ( 2
3)) - 2 plus 3 equals 5.
- NIL
52Read
- The standard function for input is read.
- When given no arguments, it reads from the
default place, which is usually standard input. - gt (defun ask (string)
- (format t A string)
- (read))
- ask
- gt (ask How old are you? )
- How old are you? 29
- 29
53Local Variables
- One of the most frequently used operators in CL
is let. - This allows local variables to be used in a
function. - A let expression has two parts.
- First comes a list of instructions for creating
variables, each of the form var or (var
expression). - Local variables are valid within the body of the
let. - After the list of variables and values comes the
body of expressions, which are evaluated in order.
gt (let ((x 100) (y 200)) (print ( x y))
(setq x 200) (print ( x y))
foo) 300 400 foo
54A let example
- gt (defun ask-number () (format t Please
enter a number. ) (let ((val (read))) - (if (numberp val)
- val (ask-number))))
- ASK-NUMBER
- gt (ask-number)
- Please enter a number. number
- Please enter a number. (this is a number)
- Please enter a number. 52
- 52
55Global variables
- Global variables are visible throughout the
program. - Global variables can be created by giving a
symbol and a value to defparameter or defvar. - gt (defparameter foo 1)
- FOO
- gt foo
- 1
- gt (defvar bar ( foo 1))
- BAR
- gt bar
- 2
- gt (defvar bar 33)
- BAR
- gt bar
- 2
Note (defparameter v e) creates a global
variable named v and sets its value to be
e. (defvar v e) is just like defparameter if no
global variable named v exists. Otherwise it
does nothing.
56Global constants
- You can define a global constant, by calling
defconstant. - gt (defconstant limit 100)
- LIMIT
- gt (setf limit 99)
- - SETQ the value of the constant LIMIT may
not be altered - 1. Break 5gt
- The plus-something-plus is a lisp convention to
identify symbols as constants. Just like
star-something-star is a lisp convention to
identify global variables.
57When in doubt
- When in doubt about whether some symbol is a
global variable or constant, use boundp. - gt (boundp foo)
- T
- gt (boundp fishcake)
- NIL
58Assignment
- There are several assignment operators in Common
Lisp set, setq and setf - the most general assignment operator is setf.
- We can use it to assign both local and global
variables - gt (setf blob 89)
- 89
- gt (let ((n 10))
- (setf n 2)
- n)
- 2
59Setf
- You can create global variables implicitly just
by assigning them values. - gt (setf x (list a b c))
- (A B C)
- However, it is better lisp style to use
defparameter to declare global variables. - You can give setf any even number of arguments
- (setf a 1 b 2 c 3)
- is the same as
- (setf a 1)(setf b 2)(setf c 3)
60setf
- You can do more than just assign values to
variables with setf. - The first argument to setf can be an expression
as well as a variable name. - In such cases, the value of the second argument
is inserted in the place referred to by the
first - gt (setf (car x) n)
- N
- gt
- (N B C)
61Functional programming
- Functional programming means writing programs
that work by returning values, instead of by
modifying things. - It is the dominant programming paradigm in Lisp.
- Must built-in lisp functions are meant to be
called for the values they return, not for
side-effects.
62Examples of functional programming
- The function remove takes an object and a list
and returns a new list containing everything but
that object - gt (setf lst (b u t t e r))
- (B U T T E R)
- gt (remove e lst)
- (B U T T R)
- Note remove does not remove an item from the
list! The original list is untouched after the
call to remove - gt lst
- (B U T T E R)
- To actually remove an item from a list you would
have to use setf - gt (setf lst (remove e lst))
- Functional programming means, essentially,
avoiding setf, and other assignment macros.
63How remove could be defined
- Heres how remove could be defined
- (defun remove (x list)
- (cond ((null list) nil)
- ((equal x (car list))
- (remove x (cdr list)))
- (t (cons (car list) (remove x (cdr
list)))))) - Note that it copies the top-level of the list.
64Iteration
- When we want to do something repeatedly, it is
sometimes more natural to use iteration than
recursion. - This function uses do to print out the squares of
the integers from start to end - (defun show-squares (start end)
- (do ((i start ( i 1)))
- ((gt i end) done)
- (format t A A i ( i i))))
65do
- The do macro is CLs fundamental iteration
operator. - Like let, do can create variables, and the first
argument is a list of variable specifications.
Each element is of the form (var initial
update) where variable is a symbol, and initial
and update are expressions. - The second argument to do should be a list
containing one or more expressions. - The first expression is used to test whether
iteration should stop. In the case above, the
test expression is (gt i end). - The remaining expression in this list will be
evaluated in order when iteration stops, and the
value of the last will be returned as the value
of the do, done in this example. - The remaining arguments to do comprise the body
of the loop.
66Dolist
- CL has a simpler iteration operator for handling
lists, dolist. - (defun len (lst)
- I calculate the length of lst
- (let ((l 0))
- (dolist (obj lst) (setf l ( l 1)))
- l))
- Here dolist takes an argument of the form
(variable expression), followed by a body of
expressions. - The body will be evaluated with variable bound
to successive elements of the list returned by
expression.
67eval
- You can call Lisps evaluation process with the
eval function. - gt (setf s1 '(cadr '(one two three)))
- (CADR '(ONE TWO THREE))
- gt (eval s1)
- TWO
- gt (eval (list 'cdr (car '((quote (a . b)) c))))
- B
68Functions as objects
- In lisp, functions are regular objects, like
symbols, or strings, or lists. - If we give the name of a function to function,
it will return the associated object. - Like quote, function is a special operator, so we
dont have to quote the argument - gt (defun add1 (n) ( n 1))
- ADD1
- gt (function )
- ltSYSTEM-FUNCTION gt
- gt (function add1)
- ltCLOSURE ADD1 (N) (DECLARE (SYSTEMIN-DEFUN
ADD1)) (BLOCK ADD1 ( N 1))gt
69Functions as objects
- Just as we can use as an abbreviation for
quote, we can use as an abbreviation for
function - gt
- ltSYSTEM-FUNCTION gt
- This abbreviation is known as sharp-quote.
- Like any other kind of object, we can pass
functions as arguments. - One function that takes a function as an argument
is apply.
70Apply
- Apply takes a function and a list of arguments
for it, and returns the result of applying the
function to the arguments - gt (apply (1 2 3))
- 6
- It can be given any number of arguments, so long
as the last is a list - gt (apply 1 2 (3 4 5))
- 15
- A simple version of apply could be written as
follows - (defun apply (f list) (eval (cons f list)))
71Funcall
- The function funcall is like apply but does not
need the arguments to be packaged in a list - gt (funcall 1 2 3)
- 6
- It could be written as
- (defun funcall (f rest args)
- (eval (cons f args)))
72Types
- In CL values have types, not variables.
- You dont have to declare the types of variables,
because any variable can hold objects of any
type. - Though type declaration is never required, you
may want to make them for reasons of efficiency.
- The built-in CL types form a hierarchy of
subtypes and supertypes. - The type t is the supertype of all types, so
everything is of type t.
73gt (typep 27 t) T gt (typep 27 atom) T gt
(typep 27 number) T gt (typep 27 real) T gt
(typep 27 rational) T gt (typep 27
integer) T gt (typep 27 fixnum) T gt (typep
27 vector) NIL
t
atom
number
real
rational
integer
fixnum
27
74Summary
- Lisp
- Syntax
- Recursion
- LISP facilities
- Common Lisp
- http//www.cs.ucdavis.edu/vemuri/classes/ecs170/l
ispintro.htm