0000.final Lisp 2011
0000.final Lisp 2011
0000.final Lisp 2011
Control of LISP Evaluation: quote and eval Programming in LISP: Creating New Functions Program Control in LISP: Conditionals and Predicates Functions, Lists, and Symbolic Computing Lists as Recursive Structures Nested Lists, Structure, and car/cdr Recursion Binding Variables Using set Defining Local Variables Using let Data Types in Common LISP
Symbolic
Why do we care about symbols?
Understand human cognition with a language like symbolic processing
Characteristics of LISP
1. 2. Language for artificial intelligence programming
a. Originally designed for symbolic computing
Imperative language
a. Describe how to perform an algorithm b. Contrasts with declarative languages such as PROLOG
3.
Functional programming
a. Syntax and semantics are derived from the mathematical theory of recursive functions. b. Combined with a rich set of high-level tools for building symbolic data structures such as predicates, frames, networks, and objects
4.
Atom
Letters (upper, lower cases) Numbers Characters : * + - / @ $ % ^ & _ < > ~ . Example
3.1416 Hyphenated-name *some-global* nil
SPECIAL FORMS:
1. Forms not evaluated according to the evaluation rule.
2. Special forms: defun, defparameter, setf, let, case, if, function, quote.
Read-Eval-Print
Interactive Environment
User enters s-expressions LISP interpreter prints a prompt
If you enter Atom: LISP evaluates itself (error if nothing is bound to the atom) List: LISP evaluates as an evaluation of function, i.e. that the first item in the list needs to be a function definition (error if no function definition is bound for the first atom), and remaining elements to be its arguments.
> (* 7 9) 63
Why LISP?
Especially designed for symbol manipulation. Provides built-in support for lists (everything is a list..) Automatic storage management (no need to keep track of memory allocation). Interactive environment, which allows programs to be developed step by step. That is, if a change is to be introduced, only changed functions need to be recompiled.
LISTS
1. Primitive aggregating type. 2. Primitive functions: first, second, ..., length, last. append, cons, list.
S-expression
nil is the only s-expression that is considered to be both an atom and a list.
An atom is an s-expression. If s1, s2,, sn are s-expressions, then so is the list (s1 s2 sn).
Everything's a List!
Data (a b c) Functions (defun
plus (x y) (+ x y))
Simple syntax:
(function-name arg1 arg2 )
Accessing a list
(car (a b c)) ==> a (cdr (a b c)) ==> (b c) (first (a b c)) ==> a (second (a b c)) ==> b (nth 1 (a b c)) ==> b
Constructing a list
(cons a (b c)) ==> (a b c) (cons a nil) ==> (a) (cons (a b) (c d)) ==> ((a b) c d)
Artificial Intelligence
17
Artificial Intelligence
18
Dynamic
Functions are first-class objects
Pass functions as arguments to other functions
USER(1): (+ 1 2 3) 6 USER(2): (apply #'+ '(1 2 3)) 6
Name Calling
Lisp remembers function names separately from variable names
USER(22): (defun add (x y) (+ x y)) ADD USER(23): (setf add 9) 9 USER(24): add 9 USER(25): #'add #<Interpreted Function ADD>
Basic terminology
Atoms: word-like indivisible objects which can be numbers or symbols. Lists: sentence-like objects formed from atoms or other lists, and enclosed in parentheses. S-expressions: compositions of atoms and lists. Procedures: step by step specifications how to do something. Primitives: procedures supplied by the LISP itself Example: (+ 5 6) User-defined procedures: procedures introduced by the programmer. Example: (students 'anna) Program: a collection of procedures working together.
S-expressions
An s-expression can have other s-expressions nested in it. Examples:
(+ (* 5 7) ( / 2 4)) (This (is a dog) (or a cat))
Expressions can be interpreted both, procedurally and declaratively. If interpreted procedurally, an expression provides a direction for doing something. Such an expression is called a form, and its first element is the name of a procedure to be used to produce the value. The process of computing the value of an expression is called evaluation. If interpreted declaratively, expressions represent data.
Evaluation of atoms
The value of a number is the number itself.
Example: 5 ==> 5
The value of the symbol T is T (true). The value of the symbol NIL is NIL (false). The symbol NIL and the empty list ( ) are the same thing. Variables are names of memory locations. The contents stored in a given memory cell is the value of the variable serving as a name of this location.
Example: Let x be a variable, and 5 be the contents of the memory cell called x. Then, the value of x is 5.
Numbers
Integers: 179, 45 Ratio: 5/7, 7/9 Floating point: 5.2, 7.9 Examples: * (/ 25 5) 5 * (/ 46 9) 46/9 ; do not divide evenly * (float (/ 46 9)) 5.111111 * (round (/ 46 9)) 5 ; the nearest integer 1/9 ; the remainder
Predicates
Example
(oddp 3) not (minusp 6) (numberp 17) ; whether its argument is odd or
Example
(defun square (x) (* x x)) (defun hypotenuse (x y) (sqrt (+ (square x) (square y))))
;the length of the hypotenuse is ;the square root of the sum of ;the square of the other sides.
USING FUNCTIONS:
1. (setf names '((john x ford) (peter p rabbit) (fabianna f wayne))) (mapcar #'last-name names) --> (ford rabbit wayne) #' from name of function to function object. mapcar primitive. 2. (defparameter *titles* '(Mr Mrs Miss Madam Ms Sir Dr Admiral Major General))
(defun first-name (name) "Select first name from a list representing a name." (if (member (first name) *titles*) (first-name (rest name)) (first name))) (if <test> <then-part> <else-part>)
(first-name '(Madam Major General Paula Jones)) --> Paula 3. Trace functions
Binding variables
Examples of setf (setf x 1) ==> 1 (setf a 2) ==> 2 (+ a x) ==> 3 (setf l (x y z)) ==> (x y z) (setf (car l) g) ==> g l ==> (g y z)
Recursion
Recursive Functions
Functions that call themselves A partial LISP version of Martins solution (defun find-enemy (guest-list enemies)
(cond ( (member (first guest-list) enemies) T ) ; Yes, there is an enemy ( T (find-enemy (rest guest-list enemies) ) ) ; this is the recursion
) ; end of cond
) ; end of defun
In English: If the first person on the guest-list is a member of the enemies list, then return true, otherwise call the function again with the rest of the list. But, this isnt very good. What if there are no guests who are enemies youll try to keep going until you get an error..
We need to add something that will build a list of the enemies.. How do we build lists?????-> we use cons
The answer --(defun identify-enemy ( guest-list enemies) (cond ( (null guest-list) NIL ) ; Reached the end of the guest list. ( (member (first guest-list) enemies) (cons (first guest-list) (identify-enemy (rest guest-list) enemies))) ; ( T (identify-enemy (rest guest-list ) enemies ) ) ) ; end of cond ) ; end of defun
guest-list = (micky snowwhite bishop robocop sirlancelot )) enemies = (robocop modred) (this is always the same so I wont repeat it) (find-enemy guest-list enemies) guest-list = (snowwhite bishop robocop sirlancelot) (find-enemy guest-list enemies) guest-list = (bishop robocop sirlancelot) (find-enemy guest-list enemies) guest-list = (robocop sirlancelot) -> this is where it finds robocop and calls cons --- BUT BEFORE actually do the cons, I make the recursive call with.
Recursion Problem
Write a function called stop that takes a list and a number and returns a list that does not exceed the number. For example: (stop (this is a list for recursion) 4) -> (this is a list)
We need to define a function that will take two arguments How are we going to stop it? We want to return a list.so we will need to create a new list (which means a cons).
Break the task down into smaller subtasks (e.g., using recursion with a combination of first/rest) Know how to synthesize partial solutions generated by subtasks into an overall solution. (e.g., using CONS, APPEND, LIST, +, etc.) Look at the arguments separately, and determine what needs to be passed into the function which arguments need to change and how should they be changed (e.g., decremented, added, rest, etc. If all else fails, make two functions --- one calls the other to do the work.
How to declare local variables (we are going to need this for iterative functions)?
(LET ( ( <var1> <val1> ) ... ( <vark> <valk> ) ) <exp1> ... <expN> ) LET is your way to set up temporary variables. You can initialize each local variable to its value concurrently, then evaluates expressions sequentially. It returns the result of evaluating the last expression. The default value of local variables declared by LET is NIL.
Recursion Templates
Recursion Templates
Recursion template
A few standard forms of recursive Lisp functions. You can create new functions by choosing a template and filling in the blanks.
Recursion templates
Double-Test Tail Recursion Single-Test Tail Recursion Single-Test Augmenting Recursion List-Consing Recursion Simultaneous Recursion on Several Variables Conditional Augmentation Multiple Recursion CAR/CDR Recursion
Example :
Func : ANYODDP
End-test-1 : (NULL X) End-value-1 : NIL End-test-2 : (ODDP(FIRST X)) E nd-value-2 : T Reduced-x : (REST X)
(defun anyoddp (x) (cond ((null x) nil) ((oddp (first x)) t) ((t (anyoddp (rest x))))
Example :
Func : FIND-FIRST-ATOM End-test : (ATOM X) End-value : X Reduced-x : (FIRST X) (defun find-first-atom (x) (cond ((atom x) x) ((t (find-first-atom (first x))))
Example1 :
Func :
End-test : End-value : Aug-fun : Aug-val : Reduced-x :
COUNT-SLICES
(NULL X) 0 + 1 (REST X)
Example :
Func : LAUGH End-test : (ZEROP N) New-element : HA Reduced-n : (- N 1) (defun laugh (n) (cond ((zerop n) nil) (t (cons ha (laugh (- n 1))))))
Example :
Func : MY-NTH End-test : (ZEROP N) End-value : (FIRST X) Reduced-n : (- N 1) Reduced-x : (REST X) (defun my-nth (n x) (cond ((zerop n) (first X) (t (my-nth (- n 1) (rest x)))))
Example
Func : End-test : End-value : NIL Aug-test : Aug-fun : Aug-val : Reduced-x : (REST X) EXTRACT-SYMBOLS (NULL X) (SYMBOLP (FIRST X)) CONS (FIRST X)
Multiple Recursion(1/2)
Template :
(DEFUN func (X) (COND (end-test1 end-value-1) (end-test2 end-value-2) (T (combiner (func first-reduced-n) (func second-reduced-n)))))
Example :
Func : End-test-1 : End-value-1 : End-test-2 : End-value-2 : Combiner : First-reduced-n : Second-reduced-n : (- N 2) FIB (EQUAL N 0) 1 (EQUAL N 1) 1 + (- N 1)
Multiple Recursion(2/2)
(defun fib (n) (cond (equal n 0) 1) (equal n 1) 1) (t (+ (fib (- n 1)) (fib (- n 2))))))
Example :
Func : End-test-1 : End-value-1 : End-test-2 : End-value-2 : Combiner : FIND-NUMBER (NUMBERP X) X (ATOM X) NIL OR
Iteration
An Example of LET
Is the situation of the party likely to be safe for you ? That is, are there more friends then enemies at the party! (defun is-safe-p ( guests ) (let ( (friendly-guests nil) (hostile-guests nil) ) (setq friendly-guests (identify-friends guests)) (setq hostile-guests (identify-enemy guests)) (> (length friendly-guests) (length hostile-guests) ) ))
Let*
Let* evaluates ALL of the expressions before ANY of the variables are bound. Let* allows you to evaluate things in the order that they are listed (this is not necessarily true of LET) Example: (let* ((sum (+ 8 3 4 2 7)) ; sum needs value (mean (/ sum 5))) (* mean mean)) ***Most of the time it doesnt matter, but check this if you keep getting errors.
Iteration
The simplest form of iteration is the LOOP (loop (<test condition> ) (return <optional var/val) [body] ) ;end loop
Example Loop
(let ((counter 1)) ; initializing my variable (loop (If (= counter 2) (return (+ counter 5)) (+ counter 1)))) 6 is returned.
Another Example
(defun test () (let ((n 0) (lis nil)) ; initializing (loop (if (> n 10) (return lis) (setq lis (cons n lis))) ; this is end of if (setq n (+ n 1))))) => (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
dotimes
Use dotimes for a counted loop (dotimes (<var--count> <intobj- upper limit> [retobj>]) <body>) (defun test () (let ((sum 0)) (dotimes (x 5 sum) ; x var initialized (print x) (print sum) (setq sum (+ sum x)))))
Dolist
Use DOLIST to process elements of a list. This is like cdring down the list recursion! (dolist (<var><list> [<retobj>] <body>)
Evaluates <list> ;which must be a list The var is then bound to each item in list
Example dolist
(defun sq-list (lst1) (let ((lst2 nil)) (dolist (ele lst1 (reverse lst2)) ; assigns first element lst1 to ele again ;remember that were first/resting through list. ; will go through each element of lst1 ; will return the reverse of lst2 (setq lst2 (cons ( * ele ele ) lst2))))) (sq-list (1 2 3 4) (1 4 9 16)
the
Another example: (defun greet (people) (dolist (person people) (print (append (so nice to see you) (list person)))))
(setq guests (sally bobo mr-potato-head)) (greet guests) -> (so nice to see you sally) (so nice to see you bobo) (so nice to see you mr-potato-head)
The Do iteration
The DO function (do ((<var1> [<init1> [<step1>]]) . (<varn [<initn>[stepn>]])) (<end-pred><fn>..<fm> <retobj >) body-exp1 body-exp2 [<body>]
Example of Do
Countdown (defun iter (max) (do ((num max (- num 1)))
; assign max to num subtract 1 from num in loop ;
Another example
Summing all integers (defun iter-sum (max) (do ((num max (- num 1)) (sum 0 (+ sum num))) ((<= num 0) sum))) In English: Assign max to number, and 0 to sum. Each time through the loop, subtract 1 from num and add sum to number. When Number is less than or equal to 0, return sum.
Yet Another
(defun reverse-list (ls) (if (listp ls) (do ((new-ls () (cons (first old-ls) new-ls)) (old-ls ls (rest old-ls))) ((null old-ls) new-ls) ) ) )
[user]: (reverse-list '(3 1 4 1 5 9)) (9 5 1 4 1 3) * With do function, you probably dont need a let --- because its in the do
Iterative Function
Write an iterative function called stop that takes a list and a number and returns a list that does not exceed the number
EVAL
(EVAL <exp>) invokes the evaluation procedure. > (EVAL (LIST + 4 5)) 9 > (SETQ A X) X > (SETQ X 100) 100
Create a function to recognize cups based on the description learned: (defun create-cup-recognizer ( cup-description ) (eval (list defun cup-recognizer ( obj ) (list subset (list quote cup-description) obj) ))) subset tests whether the first arg is a subset of the second arg. > (create-cup-recognizer cup-def) cup-recognizer
APPLY
(APPLY <fn-name> <arg-list> ) >(APPLY CONS ( A ( B C ) ) ) (A B C) > (APPLY CAR ( (A B C) ) ) A > (SETQ OP +) + > (APPLY OP ( 5 3 ) ) 8
>(FUNCALL CONS A ( B C ) ) (A B C) > (FUNCALL CAR (A B C) ) A > (SETQ OP +) + > (FUNCALL OP 5 3 ) 8 > (SETQ OP -) > (FUNCALL OP 5 3 )
Lisps success as a teaching language isnt a coincidence. It has a unique simplicity and mathematical elegance that corresponds to the concepts that are taught in programming.
Twenty years ago, these were true, but Lisp has evolved, and the requirements on programming languages have changed.
Software costs outweigh hardware costs; Lisps fast development can reduce costs significantly. Lisp has changed to meet new requirements; today it has as much Pascal in its ancestry as it does traditional Lisp.
What is Lisp?
Lisp is an acronym for list processing Derived from Churchs lambda calculus, but made efficiently computable Originally designed for symbolic processing, eg. differentiation and integration of algebraic expressions Data as symbolic expressions; simple, general data structures, for both programs and data. Consistent; everything in Lisp is a first-class object, numbers, lists, functions, symbols, objects, etc. Lisp has a thirty-odd year long history of success; it has a culture, and has been proved many times over.
Scheme;
designed as a teaching language, and in common use today. a small, clean gem-like language with Pascal in its ancestry.
Detecting errors at run-time is easy; the debugger will appear whenever there is a type error.
Is Lisp object-oriented?
The Common Lisp object system is perhaps the most advanced object system in the world. It features:
Multiple inheritance Multimethods; dispatching on more than one parameter
Slot name
Class name
Superclasses
Method name Parameters
(defclass stack ()
((elements :initform ()
:accessor stack-elements))) (defmethod clear-stack ((my-stack stack))
(defmethod pop-element ((my-stack stack)) (check-type (stack-elements my-stack) cons) (pop (stack-elements my-stack)))
defclass defmethod setf push/pop defines a class defines a method assignment Common Lisp stack primitives
Calling (append-list stack1 stack2) calls the third method, which calls the second method, which calls the first method, and then returns the final result.
Cascades of languages
Lisp programs often end up as cascades of languages, starting with general-purpose ones which gradually become more specialised to the task.
Timetabling language
Scheduling language Constraint language Lisp
Exploration of the underlying mechanism makes programs easier to understand. Lisp is a natural for this.
Debugging in Lisp
Lisp has an interactive debugger. When an error happens, a window like this appears, and the inspector can be used to help find the problem.
If..then..else
IF <test> <then> <else> (If (> n 1) (+ n 1) (* n n)) In English: If n is greater than 1 then add 1 to n, else times n by itself. You can also have just: (If (> n 1) (+ n 1)) -> but it will return a nil Try and avoid nested ifs.
Functions as Arguments
EVAL APPLY Mapping Functions
Homework Problems
Homework Problems
Problems: 1. Write a function (power 3 2) = 3^2 = 9 2. Write a function that counts the number of atoms in an expression. (count-atoms '(a (b) c)) --> 3 3. (count-anywhere 'a '(a ((a) b) a)) --> 3 4. (dot-product '(10 20) '(3 4)) --> 10x3 + 20x4 = 110 5. Write a function (flatten '(a (b) () ((c)))) --> (a b c) which removes all levels of parenthesis and returns a flat list of atoms. 6. Write a function (remove-dups '(a 1 1 a b 2 b)) --> (a 1 b 2) which removes all duplicate atoms from a flat list. (Note: there is a built-in remove-duplicates in Common Lisp, do not use it).
Solutions 1-3
(defun power (a b) "compute a^b - (power 3 2) ==> 9" (if (= b 0) 1 (* a (power a (- b 1))))) (defun count-atoms (exp) "count atoms in expresion - (count-atoms '(a (b) c)) ==> 3" (cond ((null exp) 0) ((atom exp) 1) (t (+ (count-atoms (first exp)) (count-atoms (rest exp)))))) (defun count-anywhere (a exp) "count performances of a in expresion (count-anywhere 'a '(a ((a) b) (a))) ==> 3" (cond ((null exp) 0) ((atom exp) (if (eq a exp) 1 0)) (t (+ (count-anywhere a (first exp)) (count-anywhere a (rest exp))))))
Solutions
(defun flatten (exp) "removes all levels of paranthesis and returns flat list of atomsi (flatten '(a (b) () ((c)))) ==> (a b c)" (cond ((null exp) nil) ((atom exp) (list exp)) (t (append (flatten (first exp)) (flatten (rest exp))))))
Homework
VECTORPLUS X Y
: Write a function (VECTORPLUS X Y) which takes two lists and adds each number at the same position of each list.
Example
(VECTORPLUS (3 6 9 10 4) (8 5 2))
(11 11 11 10 4)
Solution
(DEFUN VECPLUS (X Y) (COND ((NULL X) Y) ((NULL Y) X) (T (CONS (+ (CAR X) (CAR Y) (VECPLUS (CDR X) (CDR Y))))))
For Homework
Representing predicate calculus with LISP x likes (x, ice_cream)
(nott S)
S1 S 2
S1 S 2 S1 S2 S1 S 2
(ANDD S1 S2)
(ORR (imply (equiv S1 S2) S1 S2) S1 S2)
For Homework
Examples of predicates
true, false likes (george, kate) likes (x, george) likes (george, susie) likes (x, x) likes (george, sarah, tuesday) friends (bill, richard) friends (bill, george) friends (father_of(david), father_of(andrew)) helps (bill, george) helps (richard, bill) equals (plus (two, three), five)
For Homework
(DEFUN atomic_s (Ex) (cond ((member Ex (true false)) T) ((member (car Ex) (likes )) (Test_term (cdr Ex))) (T nil))) (DEFUN Test_term (ex1) (cond ((NULL ex1) T) ((member (car ex1) (george ..) (test_term (cdr ex1))) ((VARP (car ex1)) (test_term (cdr ex1))) ((functionp (car ex1)) (test_term (cdr ex1))) (T nil)))
Exercises
Evaluate the following: (setq x 'outside) (let ((x 'inside) (y x)) (list x y)) (let* ((x 'inside) (y x)) (list x y))