View
225
Download
1
Embed Size (px)
Citation preview
1
Programming Languages ILISP
© 1996 by Matthew Smosna
June 23, 1996
2
LISP
LISP = LISt Processing language Motivation: language for Artificial Intelligence
– Symbolic computation
– dynamic structures Precursors:
– IPL: 1950’s (Newell, Simon, Shaw)
» pseudo-code with lists; recursion added later
– FPL: 1956
» FORTRAN with lists
– LISP: 1960
» John McCarthy
3
LISP (cont’d)
There are many dialects of LISP!
– Franz Lisp, Portable Standard Lisp (PSL), LISP 1.5, Zlisp, MacLisp, Zetalisp
Two recend (and important) dialects:
– Common Lisp: “Standardized LISP”
» incorporated many features of older LISP’s
» commercial standard (the “Ada” of LISPs)
» big and bulky
– Scheme: 1975 (still being revised)
» A simple, clean dialect of LISP
» lexically scoped (static scoping)
4
LISP (cont’d)
Most of the discussion is valid for all dialects of LISP.
– Some will be Scheme-specific.
– The programming assignment will be in Scheme. Every language construct is an expression.
– (f arg1 arg2 .. argn) Consists of a function and some arguments (may be zero
args) Constants are functions that evaluate to themselves
– Like “xy” or 6.
5
LISP (cont’d)
Every expression returns a value!
– Example: If is a function that takes three arguments:» (if a b c ) => b if a is true, else c
6
LISP operations
Arithmetic operations:– (plus x y) or (+ x y )– (times x y) or (* x y )
In Scheme (or T):– (add x y) or (+ x y)
7
LISP operations (cont’d)
Generalized conditional:
– (cond (a1 b1) (a2 b2) ... (an bn))
Example:– (cond ((= x y) x) ((< x y) y) ((t (+ x y)))
The symbol evaluatingto true; in Scheme youcan say else.
For the first ai
that evaluates totrue, evaluate biand return thatvalue.
8
Applying functions
Applying functions:– (8) => 8– (+ 2 3) => 5
9
Anonymous functions
Big deal:– (lambda (x) (+ x x)) => function– ((lambda (x) (+ x x)) 3 ) => 6
These are anonymous functions! How about named functions?
– Here Scheme is different.
Big deal Param list Function body
10
Definitions
Define variable expression using define– Valid at top level, i.e., not inside anything.
(define x 3)
(+ x 1) => 4
(define double (lambda (x) (plus x x)))
(double 4) => 8
11
Definitions (cont’d)
More:
(define fact (lambda (n) (if (< n 2) 1 (* n (fact (- n 1))))))
(fact 4) => 24
(fact (fact 4)) => ”big number!”
12
Assignments
Define is a declaration & initialization– set! is an assignment to a (previously declared)
variable. General format:
– (set! variable expression)
Example:– (set! a (+ 4 5))
Some implementations permit set! without a define.
13
Definitions vs. assignments
What’s the difference between a define and a set!?– define is used for definitions; set! is used for
assignments.
– A set! is used to assign to a previously bound variable; a define is used to create a definition to either a bound or unbound variable; it is an error to perform a set! on an unbound variable.
– The result of a set! is undefined; the result of a define is the variable being bound.
14
Data types
Two basic data types:
– 1. Atoms: numbers, symbols, strings
» Predefined atoms: (), nil, t» Also: 123, 'a , 'acdbc , ”acbdc”
– 2. Lists: '(a 10 who 6)» You can also have lists of lists!»'((a 1) (10 that) 6 9)
15
LISP programs
LISP programs are represented as lists!!!! Why?
– Program Data are interchangeable! Lisp interpreters can easily be implemented in LISP
16
Quiz
Question: How can you specify whether(f 1 2 3) is a function application or a list?
– Answer: By using the quote function.– (quote (f A 2 3)) is a list containing the
symbols f and A and the numbers 2 and 3.– (quote B) returns the symbol B.
As a shorthand for (quote (a b c)) use:– '(a b c)
(Quote e) = 'e
17
Quiz (cont’d)
Question: What is the result of ... ?
(set! a 'b)(print a)
Answer:
b
18
Quiz (cont’d)
Question: What is the result of:– (set! a 'b)(print 'a)
Answer:– a
19
List operations
Building a list:– () is the empty list (also '() )
» '() = NIL– '(1 2 (a b)) is the list contain 1, 2 and '(a b)– (list 1 2 'a '(b c)) => '(1 2 a (b c))
20
List operations (cont’d)
Adding an element:
– (cons new-element list) => new-list Adding an element to a list:
– (cons 'a '(1 2 3)) => '(a 1 2 3)– (cons 1 ()) => (1)– (cons '(a b) '(c d)) => '((a b) c d)– (cons '(a b) 'c)) => error
The last is an error, since last argument must be a list.
21
List operations (cont’d)
cons returns a new list!
– Does not modify its argument ...
– ... but set! does (that’s what the bang indicates).
» (It’s an assignment.) So,
– (set! a '(1 2 3))– (set! b (cons 'c a))– (print b) => (c 1 2 3)– (print a) => (1 2 3)
22
List operations (cont’d)
Accessing elements of a list:
– car: returns the first element of the list. So,
– (car '(a b c)) => 'a– (car '((a b) c)) => '(a b)– (car '()) => error
23
List operations (cont’d)
Another way of accessing elements:– cdr: returns the rest of the list (everything except the
first element). So,
– (cdr '(a b c)) => '(b c)– (cdr '((a b) (c d)) => '((c d))– (cdr ()) => error
24
List operations (examples)
So,– (car (cdr '(a b c))) => 'b– (car (car '((a b) c d) => 'a– (cdr (car (cdr (cdr '(a b (c d))))))
=> (d)
25
Some shorthand
Useful combinations of car and cdr have short names:– (car (cdr x)) => (cadr x)– (car (cdr (cdr x))) => (caddr x)– (cdr (car (cdr x))) => (cdadr x)
Basic idea behind the naming convention:
– Take the middle letters of the access functins (car, cdr) and form a single symbol starting with “c” and ending with “r”.
» Not all combinations have a shorthand.
» Depends upon the implementation.
26
Some useful predicates
(null? L) -> returns true if L (L is a list) is ( ).– (null? '(1)) => false– (null? ()) => true– (null? 6) => error
(atom? X) -> returns true if X is an atom.– (atom? 6) => true– (atom? 'x) => true– (atom? '(a b)) => false
27
Some useful predicates (cont’d)
(= x y) -> returns true if x and y are identical.– Or you can write (eq? x y)
– Represents the same number or symbol or the same list. For example:
– (eq? 6 6) => true– (eq? 'a 'b) => false
In Scheme, = is used basically for numeric equality, eq? is used for everything else.
28
Some useful predicates (cont’d)
Consider this (related) sequence:– (set! x '(1 2 3))– (eq? x x) => true– (set! y x)– (eq? x y) => true
But,– (eq? '(1 2 3) '(1 2 3)) => false– (eq? x '(1 2 3)) => false
29
True and false
Note: In LISP, true is represented by t (or #t) and false is represented by nil or ( ).– (if () 6 7) => 7
– (= 6 7) => will return “( )” ! So, the empty list is also the constant “false”. So,
– (if (cdr '(a)) 6 7) => 7
Also, anything that is not ( ) or NIL is assumed to be true!– (if (car '(a b c)) 6 7) => 6
30
Sample function
Sample function: Determine the length of a list:– (define length (lambda (L) (cond ((null? L) 0) (t (+ 1 (length (cdr L)))) )))
31
Sample function (cont’d)
Some shorthand is allowed:– (define (length L) (if (null? L) 0 (+ (1 length (cdr L)))))
The above has an implied lambda.
– There are also forms of define and lambda that are like varargs in C.
32
List representation
How are lists represented?
– “( )” is a constant (some unique value and not a valid address).
A non-empty list is represented by a cons-cell.
CAR CDR Two components:CAR & CDR
33
Examples
‘(6)
6representationfor ( )
or 6
‘(a b c) ‘a
‘b
‘c
34
Examples (cont’d)
a
db
c
‘(a (b c) d)
35
Examples (cont’d)
a
2
1
(set! a ‘(1 2))
The value of a is apointer to a cons cell.
36
Examples (cont’d)
cons creates a new cons cell.– (set! a ‘(a b))– (set! b ‘(c d))– (set! c (cons a b))
c
d
‘a
‘b
c
a b
Notice that a andb are unchanged
37
Examples (cont’d)
This is why eq? is a little strange!– (eq? x y) will only return true if x and y have the
same value:
» Same number of symbols or ( )
» Same address for a list.
38
List equality
List equality:– (define (equal x y) (cond ((atom x) (eq x y)) ((atom y) nil )) (else (and (equal (car x) (car y)) (equal (cdr x) (cdr y)) ))
Common code sequence;Base cases: take car and cdr
39
List equality (cont’d)
Remember:– (set! x '(1 2 3))(set! y x)
1
3
2
x y
The result
40
Copying lists
What if we want a copy of a list?
1
3
2
y
1
3
2
x
41
Copying lists (cont’d)
To copy a list:– (define (copy x) (if (atom x) x (cons (car x)) (copy (cdr x)))))
To create a list from atoms)– (list x y z w ... ) = (cons x (cons y ( ... ) = ”the list” (x y z w ...)
42
An exercise: Flatten
Now some fun!
– Let’s write a function called flatten that removes all internal parentheses– (flatten '((1 2) 3 (4 5) (6 7 8) (9 10))))
» ... that will yield (1 2 3 4 5 6 7 8 9 10)
– To write this we need the function append removes one pair of parens, i.e.,:» (append '(...) '(...) ) gives '(... ...)
– Or, put another way, it joins two lists together:» (append '(1 2 3) '(4 5)) => (1 2 3 4 5)
43
An exercise (cont’d)
Flatten:– (define (flatten lis) ((cond ((null? lis) nil) ((atom? (car lis)) (cons (car lis) (flatten (cdr lis)))) (t (append (flatten (car lis)) (flatten (cdr lis)))) )))
44
Append
Append: How do you combine the elements of two lists into one list?– The function append:
» ( append '(a b) '(c d)) => ‘(a b c d)
– Note that (cons ‘(a b) ‘(c d)) => ‘((a b) cd) How is append written?
– (define (append x y) (if (null? x) y (cons (car x) (append (cdr x) y))))
See how well recursion works with lists!
Eventually null
45
Reversing a list
Reverse: (Let’s reverse a list)– (define (reverse lis)
(if (null? lis) nil (append (reverse (cdr lis) (list (car lis)) )))
list: creates a list outof a set of elements.
46
Reversing a list (cont’d)
Examples:– (reverse '( (1 2) (3 4) 5) ) =>(append (reverse ‘((3 4) 5) (lis ‘(1 2))) =>(append '(5 (3 4)) ((1 2))) =>(5 (3 4) (1 2)))
47
Reversing a list (cont’d)
But this is quadratic complexity!
– To reverse a size n list, call append on sizes 1, ... , n
– Complexity = 1 + 2 + ... + n = n2 (approximately) So, “kiss off” LISP ...
– ... since basic list operations (that is, the LISP stuff) take n2 in LISP and n in Pascal.
But wait ...
48
Reversing a list (cont’d)
Consider:– (define (reverse lis) (reverse1 lis nil))– (define (reverse1 f r) (if (null? f) r (reverse1 (cdr f) (cons (car f) r)) )))
49
Reversing a list (cont’d)
Example:– reverse '( (1 2) (3 4) 5)) =>reverse1 '( (1 2) (3 4) 5) nil) =>reverse1 '( (3 4) 5) '((1 2))) =>reverse1 '(5) '((3 4) (1 2))) =>reverse1 nil '(5 (3 4) (1 2)))
50
Side effects
Lists can be modified!
– Side effects! Example:
– (set-car! L A) == (set (car L) A)– (set-cdr! L M) == (set (cdr L) M)
Not officialScheme
51
Side effects (cont’d)
Example:– (set! x '((a b) c d))
d
c
x
a
b
52
Side effects (cont’d)
Example:– (set-car! x '(1 2))
– Called replaca in old LISP.
‘d
‘c
x
1
2
a
b
53
Side effects (cont’d)
Example:– (set! x '(1 2 3))– (set-cdr! x '(4 5))
3
2
x
1
3
2
x
1
5
4
54
Side effects (cont’d)
Examples:– (set! x '(1 2 3))– (print x) => '(1 2 3)– (set! y x)– (print y) => '(1 2 3)– (set-car! y ‘8)– (print x) => '(8 2 3)– (eq? x y) => #t
x is modified.
55
Quiz
Question: What happens here?– (set! x '(a b c))– (set-cdr! x x)– (print x)
Answer: a a a a a a a a a a a...
56
Quiz (cont’d)
Question: Why? Answer:
c
b
x
a
57
Associative Lists
Assume you have a list of pairs:– L = ((a b) (x y) ... (q z))
Better L = ( (f1 s1) (f2 s2) ... (fn sn) ) The associative list is a concept that appears in many
programing languages (LISP, SETL, Perl, etc.)– (assoc x L) = first pair where car is x– (assoc 5 ((8 2) (5 4 4) (9 1) (5 1)))
» yields (5 4 4)
58
Associative lists (cont’d)
Example:– (define grades '((joe 10) (bob 2) (alice 9) (sarah 6) (ted nil) ))
– (assoc sarah grades) => (sarah 6)– (cadr (assoc sarah grades)) => 6– (assoc tom grades) => #f
59
Recursion
Recursion is the primary mechanism for repeating actions. Control structures:
– if, cond, function call
» seen already– (or x y) (cond (x t) (t y))
– (and x y) (cond (x y) (t nil))
returns value offirst true expression
returns value offirst false expression
60
Scheme Loop
Scheme loop.
– Not in all LISPs.
(do ((var1 init1 step1) ... ((vark initk stepk) (test expression) commands)
Done if test isfalse, i.e., body
Value of do
61
Scheme Loop (cont’d)
Example:– (do ((x '(10 20 30) (cdr x)) (total 0 (+ total (car x))) ((null? x) total) )
– Empty body in loop.
– Value is 60.
62
Input/output
Frequent in old LISP programs.
– Less frequent now.
» set-car!, set! I/O is an important side effect.
– (read): gets one object.– (write obj): machine readable– (display obj): human readable– (read-char), (eof-object?), (newline)
63
Input/output (examples)
Some examples:
==> (define v (read))123<cr>==> v123
64
Multiple actions
Multiple actions:– (lambda (x y) (+ x y))
– An old friend.– (lambda (x y) (+ x y) (display x) (display y) ... )
Also, body of DO loop and others (see the Scheme report)
65
More on recursion
Using recursion, it is easy to perform an operation on each element of a list.
– (instead of using vectors)– (define (addl_map a)
(cond ((null a) nil) (t (cons (+ 1 (car a)) (addl_map (cdr a)))) ))
Adds 1 to each element of a list(assumes a flat list of numbers).
Question: What is the valuereturned by (addl_map a)?
66
Function parameters
Do I have to write a different function for each operation I want to perform on the elements of a list?
– No. Pass the operation (function) as a parameter!
(define (mapcar f x) (cond ((null? x) nil) (t (cons (f (car x)) (mapcar f (cdr x))) ))
Applies the map (that is, function)f to each car (that is, item) of x.
Applies f to every element of the list X.
Application offunction f.
67
Function parameters (cont’d)
So,– (mapcar add1 '(1 2 3 4)) => (2 3 4 5)
where (define (add1 x) (+ x 1))– (mapcar times2 '(3 4 5)) => (6 8 10)
68
Higher order functions
Passing functions as parameters leads to the notion of higher order functions.
– Also known as functionals.
– They are: functions that take other functions as parameters and/or return functions.
We saw that mapcar takes a function as a parameter.
– How about returning a function as the result of an expression???
69
Higher order functions (cont’d)
Suppose:– (add1 x) adds 1 to x– (sub1 x) subtracts 1 from x
Then:– (define (foo x) (cond ((= x 1) add1) (t sub1))))
takes a parameter x; if x=1then return the function add1;otherwise return the fuction sub1.
70
Higher order functions (cont’d)
Examples:– (foo 1) => ”function add1”– (foo 2) => ”function sub1”– ((foo 2) 6) => 7– ((foo 2 18) => 17– (mapcar (foo3) '(4 5 6)
=> '(3 4 5)
71
Higher order functions and lambda
What if you wanted to add 3 to every element of a list?
– Well, you could do:» (define (add3 x) (+ x 3))» mapcar add3 '(...))
– However, if you are only doing itonce you probably don’t want to bother defining a new function “add3”.
» Instead, write an expression that behaves like the function add6.
72
Another use for lambda
A lambda expression is a “nameless” function.– (lambda (x) (+ x 3))
This returns a function which takes a parameter x and adds 3 to it.– (mapcar (lambda (x) (+ x 3)) '(1 2 3))
=> (4 5 6)– ((lambda (y) (* y z)) 6)
=> 12