You've reached the end of your free preview.
Want to read all 139 pages?
Unformatted text preview: Intro to Lisp
LISP = LISt Processing Originated w/ McCarthy (1959) Implemented Church's lambda-calculus (recursive function theory) Manipulation of symbolic information The initial Lisp was impractical (no iteration) Many versions: Franz, Mac, Inter, Common (now the
standard) Guy Steele (1990): VERY useful reference. 12 Why Lisp? First, Lisp is much more exible than most languages. Users
have such total control over what goes on that if they do
not like the syntax of the language, they may change it to
suit themselves. Suppose that you do not like the method
for de ning programs in, say, Fortran, can you do anything
about it? Short of switching to another language the answer
is clearly no. Indeed the very idea seems absurd. But not to
Lisp users. (Spector, 1995, PC.)
...The second reason for choosing lisp is the way in which
Lisp in oriented toward the manipulation of symbols as opposed to, say, numbers.Norvig, (PoAIP, p. 25):
What is it that sets Lisp apart from other languages? Why
is it a good language for AI applications? There are at least
seven important factors (from Norvig):
Built-in Support for Lists Automatic Storage Management Dynamic Typing First-Class Functions Uniform Syntax Interactive Environment Extensibility
13 Characteristics of Lisp
Interactive (somewhat super cially), Recursive,
Very simple syntax (does automatic memory
mgmt), variables not explicitly typed, may be
interpreted or compiled. Oriented toward: (1) non-numeric symbol manipulation; (2) structure building and modi cation. Programs and data have same form Lisp is the defacto standard language in AI 14 Some dierences between Lisp and
Conventional Languages
Symbolic Processing Structure Building and Modi cation Programs and data have same form | Not only assigns values to symbols, but also permits dynamic
construction and dissection of data structures
| Can construct pgms on the y and even use them Additional dierences (noted in Norvig)
Many langs distinguish between stmts and expressions.
| Statements have eects (x = 2 + 2).
| Expressions return values (2 + 2). In Lisp, ALL every expression returns a value; Some of
those expressions also have side eects.
Lexical rules are very simple. | Fewer punctuation chars, only parens and white space.
x=2+2 is one single symbol; need to insert spaces: (x = 2 + 2)
to separate the symbols. No need for semicolons as a delimiter. | Expressions delimited by parentheses. (Semi colons are for comments.) 15 Syntax of Lisp
Lisp is based on symbolic expressions or S-expressions: | An atom is an S-expression: (a) symbol (b) non-symbol (number, string, array);
Examples: X, JOHN, SETQ, 7.2, "John"
| A list is an S-expression: (S-expr S-expr );
Examples: (+ 1 2), (A (B C))
| Note: case insensitive
::: THAT'S ALL THERE IS TO THE SYNTAX!!! (except for
dot notation and special characters | we'll get to special
chars later).
S-expression
atom list
(a b 3) symbol,
number,
string,
character,
array dotted pair
(3 . a)
(a . (b . (3 . nil))) Note: A list is a special case of a dotted pair where the last cell = NIL
So, actually: an S-expression is either an atom or a dotted pair. So (A) is an abbrev for (A . NIL). Lists more commonly used than dotted pairs (convenient). Note: (nil . nil) = (() . ()) = (() . nil) = (()) 6= nil
16 Basic Idea of Using Lisp
Sit in front of terminal Enter Lisp (interactive) Now you're in a read-eval-print loop EVAL = give me an expression to evaluate; returns a
value for an s-expr. (analogy: words in sentences vs.
meaning) Lisp reads the S-expr, evaluates the S-expr, then prints
the result of the evaluation. 17 Atoms: Atoms and Lists atom
turkey
1492
3turkeys
*abc Lists:
(atom)
(atom turkey)
(atom 1492 ocean blue)
(an-atom (a list inside) and more atoms)
(a list containing 5 atoms)
(a list containing 8 atoms and a list (that contains 4 atoms))
(((a list containing a list containing a list of 11 atoms)))
()
(a list that ends with the null list ())
(not a list
(not) a list
)not again The Lisp evaluation rule:
To evaluate an atom:
If it is a numeric atom, the value is the number
Else it must be a variable symbol;
so the value is the value of the variable
To evaluate a list: Assume the first item of the list is a
function, and apply that function to the values of the remaining
elements of the list. 18 Result of Evaluation: What is the value?
Number ! number itself (e.g., 7 ! 7) String ! string itself (e.g., "hi" ! "hi") Symbol ! value of symbol (e.g., X ! 5, if X has that
value) | Symbols like variables in most langs, have a value associated
with them. Special: T, NIL List ! normally function evaluation | Normally write fcn as f(a,b, ,n) or in x a+b+ +n
| In Lisp: put f inside left paren: (f a b n)
::: ::: ::: By convention, we assume that when given a list to
evaluate, the rst atom has a value associated with it
which is the body of a function.
([name of fn] [args])
| (+ 1 2) ! 3
| First elt of list is special: applied to rest of elts. Evaluation of list: (1) eval each elt of list ( rst elt
should return fcn body, rest return args); (2) apply fcn
from 1st atom to rest. Important Note: use ' to indicate \the S-expr stated"
rather than the value of that S-expr. (e.g., 'X returns
X, whereas X returns the value stored in X). We'll run through what a sample session looks like in a
minute.
19 Quote symbol Examples:
| '2 ! 2
| 2!2
| 'John ! John
| John ! ERROR: not a bound variable
Quote: use ' to indicate \the S-expression stated" rather
than the value of that S-expression. Serves to BLOCK evaluation of following expression,
returning it literally. Example: '(Pat Kim) ! (PAT KIM)
If we just had (Pat Kim), it would consider Pat as a
function and apply it to the value of the expression Kim. 20 Sample Session
Fire up Lisp ...
(+ 1 1)
=> 2
(* 23 13)
=> 299
(+ 1 (* 23 13))
=> 300
(+ (* 2 2) (- 10 9))
=> 5
(* 2 2 2 2)
=> 16
(sqrt (* 2 2 2 2))
=> 4
(/ 25 5)
=> 5
(/ 38 4)
=> 19/2
"Hello, world!"
=> "Hello, world!"
'x
=> X
x
=> Error: Unbound variable X ; Can abort out of this (abort current
; computation and return to read-eval-print loop) 21 Sample Session (continued)
(setf x 5)
=> 5 ; Setf gives a value to a variable.
; effect and ALSO returns a value (setf y (reverse '(+ a b)))
=> (B A +) ; Reverse reverses a list. (setf l '(a b c d e))
=> (A B C D E) ; l's value will now be a list. (length l)
=> 5 ; length --> gives length of a list (append l '(f))
=> (A B C D E F)
(length l)
=> 5 It has a side ; append --> merges to lists together
; (Note use of quote; l not quoted) ; Note that the length of l has not changed. (length (append '(pat Kim) (list '(John Q Public) 'Sandy)))
=> 4
; Symbolic computations can be nested and
; mixed with numeric computations.
;;; Note: "list" puts elts into a list; doesn't merge them like "append" does.
;;; Note: Order of evaluation critical. (Eval args first.) ;;; Note: Parens MUST match --> source of bizarre errors if not.
(car l)
=> A ; (first l) (cdr l)
=> (B C D E) ; (rest l) (first (rest l))
=> B
(cons 'q l)
=> (Q A B C D E) ; MAIN CONSTRUCTOR used in Lisp. 22 Understanding LISP: Lisp Data Structures
Best way to understand Lisp: Develop an intuitive understanding of its data structures (remember: pgms and
data stored the same way). First step: forget conventional pgming langs w/ which
you are familiar (else confusion). Three notations for Lisp data structures: (1) paren/list
(printed) (2) dot (printed only if req; list notation is
abbrev. for this); (3) pictorial or graphic or box/cell
notation (never printed; shows what's going on inside). We will return to relate these three. Note: parenthesized notation = surface appearance (typing in/out at terminal) whereas pictorial notation =
what's happening below the surface (i.e., how the computer is really doing it). Need to be able to switch back and forth between these
two easily. 24 Pictorial Notation: used to describe what goes on in
Memory
Note: combinations of
CAR/CDR (up to 4), e.g.,
CADR = (CAR (CDR ..)) CONS Cell: A cell in memory (w/ left and right halves) A B A B
(CONS ’A ’B) Also: FIRST, SECOND, ...
TENTH
(car,cadr,caddr, ...) A B CAR = A CDR = B
These are off in memory Note: No SIDE EFFECT (important later) Difference Between: CONS, LIST, APPEND
nil
A B A (LIST ’A ’B) Adds one mem cell Adds one mem cell
for each elt (A . B) A
B
(APPEND ’(A) ’(B)) B (CONS ’A ’B) All args must be lists!
Last ptr of each elt
points to next elt (A B) Note: can have
(CONS ’A NIL)-> (A) nil (A B) Note: can have
(LIST ’A) -> (A)
same Suppose:
X = (A)
Y = (B)
What is (CONS X Y)?
What is (LIST X Y)? nil nil B
A nil (CONS X Y) = ((A) B) A nil B nil (LIST X Y) = ((A) (B)) 25 Quote (continued from last time) The quote function inhibits the evaluation of its argument.
It returns its argument literally. If the variable barney has
the value 22, then:
Evaluating
barney
yields
22
Evaluating
(quote barney)
yields
barney
Evaluating
(car (quote (betty bambam)))
yields
betty The single quote mark (') (it is actually an apostrophe) can
be used as an abbreviation for (quote ...). 2 Taking lists apart (continued from last time) The rst element of a list (be it an atom or another list) is
the car of the list.
(car '(alphabet soup))
=> alphabet
(car '((pickles beer) alphabet (soup)))
=>(pickles beer)
(car '(((miro (braque picasso))) leger))
=>((miro (braque picasso))) Everything except the rst element of a list is the cdr of the
list.
(cdr '(alphabet soup))
=>(soup)
(cdr '((pickles beer) alphabet (soup)))
=> (alphabet (soup))
(cdr '(((miro (braque picasso))) leger))
=>(leger) Given a complex S-expression, you can obtain any of its
component S-expressions through some combination of car
and cdr. cadr is the car of the cdr:
(cadr '(old mcdonald had a farm))
=>MCDONALD cdar is the cdr of the car:
=> (cdar '((do you)(really think so?)))
(YOU) There are more variations, at least up to 4 a's or d's:
(caddar
'((deep
(in the (nested) structure)
lies
truth)))
=> LIES 3 Taking lists apart (continued)
rst is a synonym for car second is a synonym for cadr third is a synonym for caddr ....... rest is a synonym for cdr (setf x '(eenie meenie minie moe))
=> (EENIE MEENIE MINIE MOE)
(first x)
=> EENIE
(third x)
=> MINIE
(rest x)
=> (MEENIE MINIE MOE) The null list:
(cdr '(just-one-item))
=> NIL
'()
=> NIL 4 Putting lists together cons builds lists. (cons 'woof '(bow wow))
=> (woof bow wow)
(cons '(howl) '(at the moon))
=> ((howl) at the moon) You can create any list with cons.
(cons 'naked-atom '())
=> (NAKED-ATOM)
(cons 'naked-atom nil)
=>(NAKED-ATOM) car, cdr, and cons are all non-destructive:
(setf x '(the rain in spain))
=>(THE RAIN IN SPAIN)
(car x)
=>THE
(cdr x)
=>(RAIN IN SPAIN)
(cons 'darn x)
=>(DARN THE RAIN IN SPAIN)
x
=>(THE RAIN IN SPAIN) 5 Atoms and Dotted Pairs (continued from last time) You get errors if you try to take the car or cdr of a non-nil
atom
(car 'foo)
=>
> Error: Can't take CAR of FOO.
(cdr 'foo)
=>
> Error: Can't take CDR of FOO. You get \funny dots" if you try to cons things onto non-lists
(cons 'a 'b)
=> (A . B) Although \dotted pairs" have their uses, we mostly won't
use them beyond the rst problem set. That means that
you're probably doing something wrong if you get dots in
your answers. 6 Generalized assignment (setf)
Earlier dialects: not available (used something called
setq)
setq assigns a value to a symbol (setq my-favorite-list '(fe fi fo fum))
=> (fe fi fo fum)
my-favorite-list
=> (fe fi fo fum)
setq is an exception to the normal evaluation rule; the rst argument is not evaluated. (q = quote)
But setq cannot be used for generalized vars ! rplaced
with setf.
A generalized var refers to any place a ptr may be stored.
"A has the value (3)" A
3
A
nil
"A has the value 3" 3 Other places a ptr can be stored?
car/cdr of cons cell
Asst ! replacing one ptr with another
(setf A ’(4)) (setf (car A) 4) A A
3 nil 3 nil "A has the value (4)" 4 4 nil Can use an accessor
such as CAR, CDR,
FIRST, etc. 7 More about setting variables
Lisp doesn't need type declaration because everything
is a pointer (i.e., the values of symbols have types associated w/ them; atoms, lists, integers, etc.) Typical memory org:
Lisp system
Cons nodes
Strings
Integers
Symbols Symbol: \indivisible atoms" actually have parts.
Typically each atom is a table:
X Name
Value
Function "X" (string -- not same as symbol)
(if nothing here, atom is unbound)
(function definition) Prop List
Package What does setf do? (setf x 7)
Changes value slot of X's table to point to 7 Can access slots:
(symbol-name 'reverse) ! "reverse"
(symbol-function 'reverse) ! #<compiled-fn reverse>
8 Eval
EVAL = explicit evaluation.
| (+ 3 5) ! evaluated w/o user explicitly asking for eval'n
| EVAL is applied by the system (LISP = read-eval-print loop)
| Explicit eval = extra evaluation
| Sort of the opposite of quote.
Examples: Suppose (setf x 'y), (setf y 'z)
|x!y
| (eval x) ! z
| (eval 'x) ! y
What is eval useful for?
{ retrieving value of symbol whose name is not known until runtime:
(setf a 3)
(eval 'a) ! 3
NOT REALLY A GOOD IDEA: Can use symbol-value; no reason to use eval.
{ evaluating form that is constructed at runtime: (eval (list <fn> args ...))
(eval (list 'setf arg1 arg2)) (where arg1='x and arg2=3)
evaluates (setf x 3)
Note: basically building a (trivial) function and running it on
the y; in the \old" days, this was considered the \key" to
Lisp's exibility
NOT REALLY A GOOD IDEA: Use symbol-value again:
(setf (symbol-value 'arg1) (symbol-value 'arg2))
But might be cases where don't have enough info; if the list '(setf
x 3) is passed into a fn to be evaluated, then probably best thing
to do is eval: (1) can't use funcall/apply cause setf is macro; (2)
don't know enough about the args w/o extensive testing to be able
to use (or in this case not use) symbol-value.
But in general, we no longer need eval, really. Some people (e.g.,
Norvig) say you're doing something wrong if you use it. But you
should know it is there, and that sometimes there's no choice.
9 Comments Common Lisp provides 2 ways to comment your code:
#| this
could
be a
really big comment |#
(car '(a b c)) ; this is a comment
=> A
(cdr '(here is #| a list with a comment |# huh?))
=> (IS HUH?) 10 Commonlisp Forms
Function: (+ 3 5)
Can test with (functionp x) Note: Arguments to a function can themselves be a
function (nesting): (+ (* 3 5) 5)
Macro: (setf x 1)
Can test with (macro-function x) Note: violates eval'n rule: don't eval x, only eval 1.
Special form: (if test a b)
Can test with (special-form x) Two others we'll learn about later: let, let* We'll initially concentrate on this rst type of form (the
function). We'll talk about macros in detail later. 11 Predicates
A Predicate is a function that is called to answer a yes-or-no question. A predicate returns boolean truth values (T =
true / NIL = false) T/NIL special symbols; prede ned to have self
as value. (The atom t means true, and evaluates to itself. The atom NIL means false, and
evaluates to itself.) Predicates may return t for true, or they may
return any other non-nil value. Predicates in Common Lisp take various forms,
but often end with p.
12 Predicates (continued)
1. <, > (numeric functions)
2. macros may serve as predicates: (AND t nil),
(OR t nil)
Note: implementation of these allows them to be control constructs
(and nil t t t) | stop at rst nil, (or t nil nil nil) | stop at rst t.
Note: Generally considered poor style to use and/or for side eect:
(or (setf x (<fn> ...)) (setf x 'fail)) | should use to test logical condition. 3. (atom x), (null x), (not x), (listp x), (consp x),
(numberp x), (stringp x), (arrayp x), (vectorp
x), (characterp x), (member x y :test <test>)
Note: All conses are lists, but converse not true: (consp nil) ! nil
Note: Member doesn't just return t or nil!
13 Sample Session: Predicates
(null 'fig-tree)
=> NIL
(null '(bismark))
=> NIL
(null '())
=> T
(null ())
=> T
(null nil)
=> T
(atom 'eggplant)
=> T
(atom 99)
=> T
(atom 3.141592)
=> T
(atom '(floating point number))
=> NIL
(atom nil)
=> T
(atom ())
=> T
(listp 'apple)
=> NIL
(listp '(fish and telephones))
=> T
(listp 33)
=> NIL
(listp nil)
=> T
(setq lucky-number 23)
=> 23
(evenp lucky-number)
=> NIL
(not (evenp lucky-number))
=> T 14 Sample Session: Predicates Taking More Than One
Argument
(> 22 11)
=> T
(> 11 22)
=> NIL
(<= 23 23)
=> T
(>= 23 23)
=> T
(>= 100 1)
=> T
(>= 1 100)
=> NIL
(< 1 2 3 4 5 6 7 8 9)
=> T
(< 1 2 3 4 5 6 7 8 7)
=> NIL 15 Equality
Common lisp has a variety of Equality Predicates, of which equalp is the most general (see CLtL2 p. 103).
And, or, and not allow the combination of predicates into
complex predicates.
EQ and EQUAL { two most commonly used.
EQ tests whether args eval to exact same Lisp obj
EQUAL compares any two s-expressions (lists, strings,
etc.)
= used for numbers (must be same number)
EQL: EQ or =
EQUALP | same as EQUAL but disregards case (for
strings).
Others: tree-equal, char-equal, string-equal, string=,
char= Note: these are all a special case of equal; Tree-equal tests whether
two trees are equal except that the leaf nodes are expected to be
symbol atoms (not, eg., strings)
Note: can specify :TEST such as string=. x
'x
'0
'(x)
'"xy"
'"Xy"
'0
'0 y
'x
'0
'(x)
'"xy"
'"xY"
'0.0
'1 =
err
T
err
err
err
nil
nil eq
T
?
nil
nil
nil
nil
nil eql
T
T
nil
nil
nil
nil
nil equal
T
T
T
T
nil
nil
nil equalp
T
T
T
T
T
T
nil
16 Equality: Need to think about what's happening in
memory
So far: S-exprs drawn so that
symbol referenced more than once
drawn multiple times in memory What’s really going on? nil nil
A B A B EQ
A In reality, both pointers to A point to the SAME symbol
(i.e., the same exact mem location) EQ: tests for memory location exactly | therefore,
atoms only! LISP automatically makes sure that all refs to some
symbol actually point to the UNIQUE point in mem
that the symbol happens to be stored physically. This
way, any info stored w/ it (e.g., its value) is accessible
from every ref. Anytime LISP sees new symbol, it adds the symbol to
its storehouse of known atoms. 17 Sample Session: Equality
(equalp 'foot 'foot)
=> T
(equalp 'nose 'ear)
=> NIL
(equalp (+ 22 33 44) (* 33 3))
=> T
(setq long-list '(1 2 3 4 can I show you out the door?))
=> (1 2 3 4 CAN I SHOW YOU OUT THE DOOR?)
(setq lucky-number 23)
=> 23
(or (equalp lucky-number (car long-list))
(equalp (* (car long-list) 2)
(car (cdr long-list))))
=> T
(and (equalp lucky-number (car long-list))
(equalp (* (car long-list) 2)
(car (cdr long-list))))
=> NIL 18 Conditionals
IF: special form (if (= x 21) (print 'blackjack))
WHEN: macro; has same form: (when (= x 21) (print 'blackjack))
Dierence: IF has else part; should use if only when there is an
else part ! (if z 'not-empty 'empty) [z is a boolean]
| IF: most useful for 2-way fork where then/else are each 1 expr
| WHEN: used for 1-way fork (then may be more than 1 expr)
What if more than 2-way fork? Use COND!
(cond (C1 ( E11 E21...))
(C2 (E21 E22 ...)) ...
(Cn (En1 En2 ...))) (if C E1 E2)
C Y E1 E2
E11 E12... C1 Y E11 E12... Cn Y N (when C E1 E2)
C Y C1 N Y E1 E2...
En1 En2... COND: Powerful multiway branching construct; Arbitrary number
of args (called clauses) Note: general form ! can have more than
one action.
Each clause is a list of s-exprs Example: (Ci Ei1 Ei2 ... Eim).
Value returned : Eim, where Ci is rst non-nil condition
(No more Ci or Ei's are evaluated.)
Convention for our class: last Ci is the constant T (guaranteed to
be non-nil).
19 Conditionals: Examples
(cond (x 'b) (y 'c) (t 'd)) What if x = 'a? (then returns b)
What if x = nil, y = t? (then returns c)
What if x = nil y = nil? (then returns d) (cond (x (setf x 1) (+ x 2))
(y (setf y 2) (+ y 2))
(t (setf x 0) (setf y 0)))
What if x = t? (then returns 3) What is x? (x = 1)
What if x = nil, y = t? (then returns 4) What are x/y? (nil/2)
What if x = nil y = nil? (then returns 0) What are x/y? (...
View
Full Document
- Spring '16
- PR. LANGAT
- Recursion, Nil, Lisp programming language