Lecture 11 - Nipissing University Word
Download
Report
Transcript Lecture 11 - Nipissing University Word
COSC3306:
Programming Paradigms
Lecture 11: Applicative
Programming with Lisp
Haibin Zhu, Ph.D.
Computer Science
Nipissing University
(C) 2003
1
Versions 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 haven’t changed much
2
Recursion
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.
3
Informal 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) ( ( ) ) )
4
Formal Syntax (approximate)
<S-expression> ::= <atom> | <list>
<atom> ::= <number> | <identifier>
<list> ::= ( <S-expressions> )
<S-expressions > ::= <empty>
| <S-expressions > <S-expression>
<number> ::= <digit> | <number> <digit>
<identifier> ::= string of printable characters,
not including parentheses
5
LISP 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.
6
Data 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.
7
T 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 isn’t NIL is “true”
NIL is both an atom and a list
– it’s defined this way, so just accept it
8
Function 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?
9
Quoting
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
10
Basic 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
11
© 2003 Brooks/Cole Publishing / Thomson Learning™
Figure 13.1 Memory representation of (cons ‘A ‘B)
12
© 2003 Brooks/Cole Publishing / Thomson Learning™
Figure 13.2 Memory representation of (cons
‘A (cons ‘CAR ‘NIL))
13
© 2003 Brooks/Cole Publishing / Thomson Learning™
Figure 13.3 Memory representation
of (cons ‘A (cons ‘B ‘C))
14
© 2003 Brooks/Cole Publishing / Thomson Learning™
Figure 13.4 A representation of list (A (BC) D)
15
© 2003 Brooks/Cole Publishing / Thomson Learning™
Figure 13.5 A representation of list ((AB) (C ) (DF))
16
© 2003 Brooks/Cole Publishing / Thomson Learning™
Figure 13.6 Cell diagram representation of list (a b c)
17
© 2003 Brooks/Cole Publishing / Thomson Learning™
Figure 13.7 Cell diagram representation of
list (a b) (c ) (d f))
18
© 2003 Brooks/Cole Publishing / Thomson Learning™
Figure 13.9 Scheme evaluation of
expression ( * ( - 5 2) (+ 2 3))
19
Other 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)
20
CAR
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)
( (X Y) Z)
A
(X Y)
(()())
()
()
undefined
21
CDR
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
22
CDR examples
If L is
Then (CDR L) is
(A B C)
( (X Y) Z)
(B C)
(Z)
(X)
()
(()())
(())
()
undefined
23
CONS
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:
CONS of
A (B C)
gives
(A B C)
24
CONS 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
25
Dotted 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
26
EQ
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
27
ATOM
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
28
COND
COND implements the
if...then...elseif...then...elseif...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
29
To be continued
COND
Member
Equal
30
Special 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
31
Form of the COND
(COND
(condition1 result1 )
(condition2 result2 )
...
(T resultN ) )
32
Defining 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) ) )
33
Example: 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
34
Rules for Recursion
Handle the base (“simplest”) cases first
Recur only with a “simpler” case
– “Simpler” = more like the base case
Don’t alter global variables (you can’t
anyway with the Lisp functions I’ve told
you about)
Don’t look down into the recursion
35
Guidelines 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.
36
Example: 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) )) ) )
37
Still more useful Functions
(LENGTH L) returns the length of list L
(RANDOM N) , where N is an integer,
returns a random integer >= 0 and < N.
38
How 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)))))
39
Lambda 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.
40
The 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)
41
The 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)
42
The special form prog
(progn expression1, expression2, …,
expressionn)
(progn (set ‘x 3) (set ‘y 4) (print (* x y)))
43
Some 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))))
44
Variations on reverse
;; either of these does O(n^2) 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)))))
45
Flatten
(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))))))
46
Higher order functions
(defun mapcar (f l)
(if (null l)
nil
(cons (apply f (list (car l)))
(mapcar f (cdr l)))))
47
Examples
http://sandbox.mc.edu/~bennet/cs404/doc/
lisp.html
http://www.cs.ualberta.ca/~tommy/ta/325/li
sp_examples.html
http://www.notam02.no/internt/cm-sys/cm1.4/doc/examples/
48
Common Lisp
49
Why 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.
50
Input and Output
Print is the most primitive output function
> (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:
> (format t “~A plus ~A equals ~A.~%” 2 3 (+ 2 3))
2 plus 3 equals 5.
NIL
51
Read
The standard function for input is read.
When given no arguments, it reads from
the default place, which is usually
standard input.
> (defun ask (string)
(format t “~A” string)
(read))
ask
> (ask “How old are you? “)
How old are you? 29
29
52
Local Variables
One of the most frequently
> (let ((x 100) (y 200))
used operators in CL is let.
(print (+ x y))
This allows local variables to
(setq x 200)
be used in a function.
A let expression has two parts.
(print (+ x y))
– First comes a list of instructions
‘foo)
for creating variables, each of the
form var or (var expression).
300
Local variables are valid within the
body of the let.
400
– After the list of variables and
foo
values comes the body of
expressions, which are evaluated
in order.
53
A let example
> (defun ask-number ()
(format t “Please enter a number. “)
(let ((val (read)))
(if (numberp val)
val
(ask-number))))
ASK-NUMBER
> (ask-number)
Please enter a number. number
Please enter a number. (this is a number)
Please enter a number. 52
52
54
Global variables
Global variables are visible throughout the
program.
Global variables can be created by giving a
symbol and a value to defparameter or defvar.
> (defparameter *foo* 1)
*FOO*
> *foo*
1
> (defvar *bar* (+ *foo* 1))
*BAR*
> *bar*
2
> (defvar *bar* 33)
*BAR*
> *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.
55
Global constants
You can define a global constant, by calling
defconstant.
> (defconstant +limit+ 100)
+LIMIT+
> (setf +limit+ 99)
*** - SETQ: the value of the constant +LIMIT+ may
not be altered
1. Break [5]>
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.
56
When in doubt
When in doubt about whether some
symbol is a global variable or constant, use
boundp.
> (boundp ‘*foo*)
T
> (boundp ‘fishcake)
NIL
57
Assignment
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:
> (setf *blob* 89)
89
> (let ((n 10))
(setf n 2)
n)
2
58
Setf
You can create global variables implicitly just by
assigning them values.
> (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)
59
setf
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:
> (setf (car x) ‘n)
N
>
(N B C)
60
Functional 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.
61
Examples of functional
programming
The function remove takes an object and a list and returns a
new list containing everything but that object:
> (setf lst ‘(b u t t e r))
(B U T T E R)
> (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:
> lst
(B U T T E R)
To actually remove an item from a list you would
have to use setf:
> (setf lst (remove ‘e lst))
Functional programming means, essentially,
avoiding setf, and other assignment macros.
62
How remove could be defined
Here’s 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.
63
Iteration
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)))
((> i end) ‘done)
(format t “~A ~A~%” i (* i i))))
64
do
The do macro is CL’s 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 (>
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.
65
Dolist
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.
66
eval
You can call Lisp’s evaluation process with the
eval function.
> (setf s1 '(cadr '(one two three)))
(CADR '(ONE TWO THREE))
> (eval s1)
TWO
> (eval (list 'cdr (car '((quote (a . b)) c))))
B
67
Functions 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 don’t have to quote the argument:
> (defun add1 (n) (+ n 1))
ADD1
> (function +)
#<SYSTEM-FUNCTION +>
> (function add1)
#<CLOSURE ADD1 (N) (DECLARE (SYSTEM::INDEFUN ADD1)) (BLOCK ADD1 (+ N 1))>
68
Functions as objects
Just as we can use ‘ as an abbreviation for
quote, we can use #’ as an abbreviation for
function:
> #’+
#<SYSTEM-FUNCTION +>
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.
69
Apply
Apply takes a function and a list of arguments for it,
and returns the result of applying the function to the
arguments:
> (apply #’+ ‘(1 2 3))
6
It can be given any number of arguments, so long as
the last is a list:
> (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)))
70
Funcall
The function funcall is like apply but does
not need the arguments to be packaged in
a list:
> (funcall #’+ 1 2 3)
6
It could be written as:
(defun funcall (f &rest args)
(eval (cons f args)))
71
Types
In CL values have types, not variables.
You don’t 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.
72
t
atom
number
real
rational
integer
fixnum
27
> (typep 27 ‘t)
T
> (typep 27 ‘atom)
T
> (typep 27 ‘number)
T
> (typep 27 ‘real)
T
> (typep 27 ‘rational)
T
> (typep 27 ‘integer)
T
> (typep 27 ‘fixnum)
T
> (typep 27 ‘vector)
NIL
73
Summary
Lisp
– Syntax
– Recursion
– LISP facilities
Common Lisp
– http://www.cs.ucdavis.edu/~vemuri/classes/ec
s170/lispintro.htm
74