650 likes | 753 Views
CSCI 2210: Programming in Lisp. ANSI Common Lisp, Chapters 5-10. Progn. Progn Creates a block of code Expressions in body are evaluated Value of last is returned (if (< x 0) (progn (format t "X is less than zero ") (format t "and more than one statement ")
E N D
CSCI 2210: Programming in Lisp ANSI Common Lisp, Chapters 5-10 CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Progn • Progn • Creates a block of code • Expressions in body are evaluated • Value of last is returned • (if (< x 0) • (progn • (format t "X is less than zero ") • (format t "and more than one statement ") • (format t "needs to be executed in the IF") • (- x) • ) • ) • Prog1 • Same as progn, except value of first expression is returned CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Block • Like a progn with • A name • An "emergency exit" • return-from - Returns from a named block • return - Returns from a block named NIL • Examples • > (block head • (format t "Here we go") • (return-from head 'idea) • (format t "We'll never see this")) • Here we go. • IDEA • > (block nil (return 27)) • 27 CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Implicit use of Blocks • Some Lisp constructs implicitly use blocks • All iteration constructs use a block named NIL (note return) • > (dolist (x '(a b c d e)) • (format t "~A " x) • (if (eql x 'c) (return 'done))) • A B C • DONE • Defun uses a block with same name as the function • > (defun foo () • (return-from foo 27)) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Iteration • DOTIMES (Review) • (dotimes (<counter> <upper-bound> <final-result>) • <body>) • Example • (dotimes (i 5) (print i)) ;; prints 0 1 2 3 4 • DOLIST • (dolist (<element> <list-of-elements> <final-result>) • <body>) • Example • (dolist (elem '(a b c d)) (print elem)) ;; prints a b c d CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Example of DOLIST • Given a list of ages of people, how many adults? • List of ages • > (setf ages '(3 4 17 21 22 34 2 7)) • Adult defined as: >= 21 years old • > (defun adultp (age) (>= age 21)) • Using Count-if • (defun count-adult (ages) (count-if #'adultp ages)) • Using dolist • (defun count-adult (ages &aux (nadult 0)) • (dolist (age ages nadult) • (if (adultp age) (setf nadult (+ 1 nadult))))) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Example (cont.) • Get the ages of the first two adults • (defun first-two-adults (ages &aux (nadult 0) (adults nil)) • (dolist (age ages) • (if (adultp age) • (progn (setf nadult (+ nadult 1)) • (push age adults) • (if (= nadult 2) (return adults)))))) • Notes • PROGN (and PROG1) are like C/C++ Blocks { … } • > (prog1 (setf a 'x) (setf b 'y) (setf c 'z)) • X • > (progn (setf a 'x) (setf b 'y) (setf c 'z)) • Z • RETURN exits the DOLIST block • Note: does not necessarily return from the procedure! • Takes an optional return value CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
DO • DO is more general than DOLIST or DOTIMES • Example • (defun do-expt (m n) ;; Return M^N • (do ((result 1) ;; Bind variable ‘Result’ to 1 • (exponent n)) ;; Bind variable ‘Exponent’ to N • ((zerop exponent) result) ;; test and return value • (setf result (* m result)) ;; Body • (setf exponent (- exponent 1)) ;; Body • Equivalent C/C++ definition • int do_expt (int m, int n) { • int result, exponent; • for (result=1,exponent=n; (exponent != 0); ) { • result = m * result; • exponent = exponent - 1; • } • return result; • } CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
DO Template • Full DO Template (There is also a DO*) • (DO ( (<p1> <i1> <u1>) • (<p2> <i2> <u2>) … • (<pN> <iN> <uN>) ) • ( <term-test> • <a1> <a2> … <aN> • <result> ) • <body> ) • Rough equivalent in C/C++ • for ( <p1>=<i1>, <p2>=<i2>,…,<pN>=<iN>; //Note: Lisp=parallel • !(<term-test>); // C/C++ has a “continuation-test” • <p1>=<u1>, <p2>=<u2>,…,<pN>=<uN>) { • <body> • } • <a1>; <a2>; … ; <aN>; • <result>; // Note: (DO…) in Lisp evaluates to <result> • // Note: <p1>,<p2>,…,<pN> are now restored to original values CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Do-expt, Loop • Here is another (equivalent) definition of do-expt • (defun do-expt (m n) • (do ((result 1 (* m result)) • (exponent n (- exponent 1))) • ((zerop exponent) result) • ;; Note that there is no body! • )) • Loop • An infinite loop, terminated only by a (return) • (loop • (print '(Say uncle)) • (if (equal (read) 'uncle) (return))) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Multiple Values • We said each lisp expression returns a value • Actually, can return zero or more values (i.e. multiple values) • > (round 7.6) ; Round returns two values • 8 • -0.4 • > (setf a (round 7.6)) • 8 ; Setf expects only one value, so it takes the first (8) • > a • 8 • How can you get all values? • > (multiple-value-list (round 7.6)) • (8 -0.4) • > (multiple-value-setq (intpart dif) (round 7.6)) • 8 • > intpart • 8 • > dif • -0.4 CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Generating Multiple Values • How? Use values • > (values 1 2 3) ; Generates 3 return values • 1 • 2 • 3 • > (defun uncons (aList) (values (first aList) (rest aList))) • UNCONS • > (uncons '(A B C)) • A • (B C) • > (format t "Hello World") • "Hello World" • NIL • > (defun format-without-return (out str &rest args) • (apply #'format out str args) • (values)) ; A function with no return value! • FORMAT-WITHOUT-RETURN • > (format-without-return t "Hello") • Hello • > CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Functions about functions • FBOUNDP - Is a symbol the name of a function? • > (fboundp '+) • T • SYMBOL-FUNCTION - returns function • > (symbol-function '+) • #<Compiled-Function + 17B4E> • > (setf (symbol-function 'sqr) #'(lambda (x) (* x x))) • #<Interpreted-Function SQR> • > (defun sqr (x) (* x x)) ; this is equivalent to above • SQR • Defun and symbol-function define global functions • Local functions can be defined using LABELS • > (defun add3 (x) • (labels ((add1 (x) (+ x 1)) • (add2 (x) (+ x 2))) • (add1 (add2 x)))) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Closures • Want a function that can save some values for future access/update • Can use global variables for this • > (setf *number-of-hits* 0) ; Global variable • 0 • > (defun increment-hits () (incf *number-of-hits*)) • INCREMENT-HITS • > (increment-hits) • 1 • > (increment-hits) • 2 • But, what if someone clobbers the variable? • > (setf *number-of-hits* "This variable is now a string") • "This variable is now a string" • > (increment-hits) • Error: '*number-of-hits*' is not of the expected type: NUMBER • Want something like "static" variables in C/C++. CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Closures (continued) • One use of closures is to implement 'static' variables safely • Closure -- Combination of a function and environment • Environment can include values of variables • > (let ((number-of-hits 0)) • (defun increment-hits () (incf number-of-hits))) • INCREMENT-HITS • number-of-hits is a free variable • It is a lexical variable (has scope) • A function that refers to a free lexical variable is called a closure • Multiple functions can share the same environment • > (let ((number-of-hits 0)) • (defun increment-hits() (incf number-of-hits)) • (defun reset-hit-counter() (setf number-of-hits 0)) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Closures (cont) • Example 1 • > (defun make-adder (n) ; returns function to add n to x • #'(lambda (x) (+ x n))) • > (setf add3 (make-adder 3)) ; returns function to add 3 • #<Interpreted function C0EBF6> • > (funcall add3 2) ; Call function add3 with argument 2 • 5 • > (setf (symbol-function 'add3-b) (make-adder 3)) • > (add3-b 5) • 8 • Example 2 - Returns an "opposite" function • > (defun our-complement (f) • #(lambda (&rest args) • (not (apply f args)))) • > (mapcar (our-complement #'oddp) '(1 2 3 4)) • (NIL T NIL T) • Tip of the iceberg in terms of possibilities CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Trace • Format • (trace <procedure-name>) • Example • > (defun factorial (x) (if (<= x 1) 1 (factorial (- x 1)))) • > (trace factorial) • Causes entry, exit, parameter, and return values to be printed • For EACH procedure being traced • > (factorial 3) • ; 1> FACTORIAL called with arg: 3 • ; | 2> FACTORIAL called with arg: | 2 • ; | | 3> FACTORIAL called with arg: | | 1 • ; | |3< FACTORIAL returns value: | | 1 • ; | 2< FACTORIAL returns value: | 2 • ; 1< FACTORIAL returns value: 6 • 6 • Untrace stops tracing a procedure: (untrace <procedure-name>) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Print, Read • Print • Example • > (print '(A B)) • Evaluates a single argument • Can be a constant (ex. 100), a variable (x), or any single expression • Prints its value on a new line • Returns the value printed • Read - reads a single expression • Example: • > (read)20 23 (A B) C • 20 ;; Note: Only the 20 is read; rest is ignored • > (progn (print 'Enter-temperature) (read)) • Enter-temperature 20 • 20 CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Format • Format • Allows more elegant printing • > (progn (print "Enter temperature: ") (read)) • "Enter temperature: " 32 • 32 • > (progn (format t "~%Enter temperature: ") (read)) • Enter temperature: 32 • 32 • The second parameter (t) is the output buffer (T=stdout) • The character “~” signifies that a control character follows • The character “%” signifies a newline (Lisp: “~%” C: “\n”) • The characters “~a” tells Lisp to substitute the next value • printf ("The value is ( %d, %d )", x, y); /* A C stmt */ • > (format t "The value is ( ~a, ~a )" x y) ;; Lisp way • > (format t "The value is ( ~10a, ~a )" x y) ; Can get fancy CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Streams • Write output to a file (e.g. knowledge base) • Prototype of with-open-file • (with-open-file (<stream name> • <file specification> • :direction <:input or :output>) • …) • Example • > (setf fact-database • '((It is raining) • (It is pouring) • (The old man is snoring))) • > (with-open-file (my-file ”myfile.lsp” :direction :output) • (print fact-database my-file)) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
My-Trace-Load • Redefine the built-in Lisp “Load” function • Example of Built In function • > (load "a.lsp") • Additional requirements • Want to print each expression that is read in. • Want to print the value returned by the expression • Definition • (defun my-trace-load (filename &aux next-expr next-result) • (with-open-file (f filename :direction :input) • (do ((next-expr (read f nil) (read f nil))) • ((not next-expr)) • (format t "~%~%Evaluating '~a'" next-expr) • (setf next-result (eval next-expr)) • (format t "~% Returned: '~a'" next-result)))) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Read-Line, Read-Char • Read-Line • Reads an individual line (terminated by a carriage return) • Returns it as a character string • > (read-line)Hello World • “Hello World” • Read-Char • Reads an individual character • Returns it as a character • > (read-char)x • #\x ;; This is Lisp notation for the character ‘x’ CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Symbols • We've used symbols as names for things • A symbol is much more than just a name • Includes: name, package, value, function, plist (Property List) • A symbol is a "substantial object" • Some functions for manipulating symbols • symbol-name, symbol-plist, intern,… • Details are in Chapter 8 of textbook CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Symbol Names • By default Lisp symbol names are upper case • > (symbol-name 'abc) • "ABC" • Can use "|" to delimit symbol names • > (list '|abc|) ; no conversion • "abc" • > (list '|Lisp 1.5| '|| '|abc| '|ABC|) • (|Lisp 1.5| || |abc| ABC) ; Note that only ABC doesn't have delimiter (default) • Intern creates new symbols • > (set (intern '|5.1/5)|) 999) • 999 • > |5.1/5)| • 999 CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Packages • Package • A name space for symbols • Large programs use multiple packages • > (defpackage "MY-APPLICATION" ;; Creates new package • (:use "COMMON-LISP" "MY-UTILITIES") ;; Other packages • (:nicknames "APP") • (:export "WIN" "LOSE" "DRAW")) ;; Symbols exported • #<The MY-APPLICATION package> • > (in-package my-application) ;; Sets this to be default • New symbols are (by default) created in default package • The default package, when Lisp is started is COMMON-LISP-USER • The COMMON-LISP packages is automatically used CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Numbers • Number crunching is one of Lisp's strengths • Many data types, automatically converted from one to another • Many numeric functions • Example: Factorial program was easier in Lisp (no overflow!) • Four distinct types • Types: Integer, Floating Point Number, Ratio, and Complex Number • Examples: 100, 123.45, 3/2, #c(a b) ; #c(a b) = a+bi • Predicates: integerp, floatp, ratiop, complexp • Basic rules for automatic conversion • If function receives floating point #'s, generally returns floating point #'s • If a ratio divides evenly (for example, 4/2), it will be converted to integer • If complex # has an imaginary part of zero, converted to a real CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Subset of Type Hierarchy Lisp Expression Return Value (setf a 12); 12 (type a 'bit); NIL (type a 'fixnum); T (type a 'integer); T (integerp a); T (rationalp a); T (realp a); T (numberp a); T CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
More on Numbers • Conversion • (float) (truncate) (floor) (ceiling) (round) … • > (mapcar #'float '(1 2/3 .5)) • (1.0 0.6667 0.5) • Comparison • Use = to compare for equality (also, <,<=, >, >=, /=) • > (= 4 4.0) • T • Other Misc. functions • Max • Min • (expt x n) = X^n • (exp x) = E^x • (log x n) = logn X; N is optional (default = natural log) • sqrt, sin, cos, tan CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Eval • Eval - Evaluates an expression and returns its value • > (eval '(+ 1 2 3)) • 6 • Top-level is also called the read-eval-print loop • Reads expression, evaluates it, prints value, loops back • > (defun our-toplevel () • (loop • (format t "%~> ") • (print (eval (read)))) • Eval • Inefficient - slower than running compiled code • Expression is evaluated without a lexical context CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Macros • Macros • A common way to write programs that write programs • Defmacro is used to define macros • Example: A macro to set its argument to NIL • > (defmacro nil! (x) • (list 'setf x nil)) • > (nil! A) ;; Expands to (setf A NIL), is then evaluated • NIL • macro-expand-1 Generates macro expansion (not eval'ed) • > (macroexpand-1 '(nil! A)) • (SETF A NIL) • T CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Macros • Typical procedure call (defun) • Evaluate arguments • Call procedure • Bind arguments to variables inside the procedure • Macro procedure (defmacro) • Macros do not evaluate their arguments • When a macro is evaluated, an intermediate form is produced • The intermediate form is evaluated, producing a value CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Example: Manually Define Pop • Review of the built in operation “Pop”: • Implements Stack data structure “Pop” operation • > (setf a '(1 2 3 4 5)) • > (pop a) • 1 • > a • (2 3 4 5) • How would you emulate this using other functions? • Attempt 1: Remove the element “1” from A • > (setf a (rest a)) • (2 3 4 5) ;; A is set correctly to (2 3 4 5), but we want “1” to be returned • Attempt 2: Remove first element AND return it • > (prog1 (first a) (setf a (rest a))) • Attempt 3: Write a Lisp expression that generates above expression • > (list 'prog1 • (list 'first a) • (list 'setf a (list 'rest a))) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Our-Pop, using Macro • Convert Lisp expression into a macro (Our-Pop) • > (defmacro our-pop (stack) • (list 'prog1 • (list 'first stack) • (list 'setf stack (list 'rest stack)))) • Note similarity to Defun • Example Call • > (OUR-POP a) • Notes • The parameter “A” is NOT evaluated • “A” is substituted for stack wherever the variable stack appears • (list 'prog1 • (list 'first a) • (list 'setf a (list 'rest a))) • Intermediate form is generated • (prog1 (first a) (setf a (rest a))) • Intermediate form is evaluated • A is set to (rest A); the first element is returned CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Our-Pop using Defun • Why doesn’t this (defun) work the same way? • > (defun our-pop (stack) • (prog1 (first stack) (setf stack (rest stack)))) • > (setf a '(1 2 3 4 5)) • > (our-pop a) • 1 • > a • (1 2 3 4 5) • Reason: Lisp passes parameters “by-value” • The value of A is COPIED into the variable “stack” • Any changes to the variable “stack” are done to the COPY, and NOT the original variable A • When the function returns, the original value of A is unchanged CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Significance of Eval Steps • Macro evaluation has several steps (as noted) • The parameter “A” is NOT evaluated • “A” is substituted for stack wherever the variable stack appears • Intermediate form is generated • Intermediate form is evaluated • Note that A is evaluated at step 4 above (not step 1) • Why does this matter? • Answer: For the same reason that it matters in C/C++ macros • You may not want arguments evaluated at all • Or, you may want them evaluated multiple times • Macros give this flexibility CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Backquotes • Significance of Evaluation Steps (cont) • Consider • > (defmacro our-if-macro (conditional then-part else-part) • (list 'if conditional then-part else-part)) • > (defun our-if-fun (conditional then-part else-part) • (if conditional then-part else-part)) • > (if (= 1 2) (print "Equal") (print "Not Equal")) • Lisp evaluates all parameters of OUR-IF-FUN before function is called • Backquote Mechanism • Forward quotes: Entire next expression is not evaluated • > (defun temp () (setf a '(a b c d e))) • Backquote: Next expression is not evaluated (with exceptions) • > (defun temp () (setf a `(a b c d e))) • > (defun temp (x) (setf a `(a b c d e ,x)) • The “,x” expression is evaluated; the value of X is used. CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Backquotes (cont.) • Exceptions - Backquote evaluates the following • ,variable - Evaluates the value of the variable • > (setf x '(h i j)) • > (setf a `(a b c ,x e f)) • (A B C (H I J) E F) • ,@variable - Splices the elements of a list • > (setf a `(a b c ,@x e f)) • (A B C H I J E F) • Backquotes simplify macro development • > (defmacro our-if-macro (conditional then-part else-part) • (list 'if conditional then-part else-part)) ;; old way • > (defmacro our-if-macro (conditional then-part else-part) • `(if ,conditional ,then-part ,else-part)) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Backquotes simplify macros • Original version of our-pop • > (defmacro our-pop (stack) • (list 'prog1 • (list 'first stack) • (list 'setf stack (list 'rest stack)))) • Our-pop redefined using backquotes • > (defmacro our-pop (stack) • `(prog1 (first ,stack) (setf ,stack (rest ,stack)))) • Syntax is much closer to the intermediate form • Macros can be defined with following parameters • Optional (&optional) • Rest (&rest) • Key (&key) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Macro Design • Macro: take a number n, evaluate its body n times • Example call • > (ntimes 10 (princ ".")) • ………. • NIL • First attempt (incorrect) • > (defmacro ntimes (n &rest body) • `(do ((x 0 (+ x 1))) • ((>= x ,n)) • ,@body)) • For example call, within body of macro • n bound to 10 • body bound to ((princ ".")) • (do ((x 0 (+ x 1))) • ((>= x 10)) • (princ ".")) • Macro works for example. Why is it incorrect? CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Inadvertent Variable Capture • Consider • Initialize x to 10, increment it 5 times • > (let ((x 10)) • (ntimes 5 (setf x (+ x 1))) • x) • 10 • Expected value: 15 • Why? Look at expansion • > (let ((x 10)) • (do ((x 0 (+ x 1))) • ((>= x 5)) • (setf x (+ x 1))) • x) • X is used in let and in the iteration • setf increments iteration variable! CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Gensym Gives New Symbol • Gensym • Generates a new (uninterned) symbol • > (defmacro ntimes (n &rest body) ; Still incorrect though • (let ((g (gensym))) • `(do ((,g 0 (+ ,g 1))) • ((>= ,g ,n)) • ,@body))) • The value of symbol G is a newly generated symbol • How does this avoid the problem? • What if the call has a variable G? • Look at the expansion of • (let ((x 10)) • (ntimes 5 (setf x (+ x 1))) • x) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Expansion of ntimes (2) • Substitute for N and BODY • > (let ((x 10)) • (let ((g (gensym))) • `(do ((,g 0 (+ ,g 1))) • ((>= ,g ,5)) • ,@((setf x (+ x 1))))) • x) • Generate intermediate form • > (let ((x 10)) • (do ((#:G34 0 (+ #:G34 1))) • ((>= #:G34 5)) • (setf x (+ x 1))) • x) • Evaluate • 15 • This works for our example … but ... CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Multiple Evaluation • What happens when we want to debug… • > (let ((x 10) (niteration 3)) • (ntimes niteration (setf x (+ x 1))) • x) • 13 • To debug, insert a print expression • > (let ((x 10) (niteration 3)) • (ntimes (print niteration) (setf x (+ x 1))) • x) • 3 • 3 • 3 • 3 • 13 • The argument is evaluated multiple times • Apparent when argument causes side-effects • What if the argument was a (setf …) • Non-intuitive: Expect argument to be evaluated only once. CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Avoiding Multiple Evaluation • Solution is to copy value when you get into macro • Use copy when needed within macro • > (defmacro ntimes (n &rest body) • (let ((g (gensym)) • (h (gensym))) • `(let ((,h ,n)) • (do ((,g 0 (+ ,g 1))) • ((>= ,g ,h)) • ,@body)))) • This is correct • > (let ((x 10) (niteration 3)) • (ntimes (print niteration) (setf x (+ x 1))) • x) • 3 • 13 CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Expansion of Ntimes (Final) • Pprint is a useful function for Pretty PRINTing expressions • > (pprint (macroexpand-1 • '(ntimes (print niteration) (setf x (+ x 1))))) • (LET ((#:G93 (PRINT NITERATION))) • (DO ((#:G92 0 (+ #:G92 1))) ((>= #:G92 #:G93)) (SETF X (+ X 1)))) • Problems of Multiple Evaluation and Inadvertent Variable Capture • Examples of errors that can occur when working with macros • Errors are common in Lisp as well as languages like C/C++ CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Multiple Evaluation in Pop • Looking back at our Pop macro • It suffers from multiple evaluation • We can't use same technique, though • Need to get the first AND do a setf to change the value • > (defmacro our-pop (stack) • `(prog1 (first ,stack) (setf ,stack (rest ,stack)))) • Textbook solution avoids multiple evaluation • Page 301 • Uses a function get-setf-expansion to get to inner details of setf CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Case Study: Expert Systems • Overview of using Lisp for • Symbolic Pattern Matching • Rule Based Expert Systems and Forward Chaining • Backward Chaining and PROLOG • Motivational example • Given: • A set of Facts • A set of Rules • Desired result • Answer complex questions and queries CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Smart Animal Guessing • Facts about an animal named “Joey” • F1. (Joey’s mother has feathers) • F2. (Joey does not fly) • F3. (Joey swims) • F4. (Joey is black and white) • F5. (Joey lives in Antarctica) • Rules about animals in general • R1. If (animal X has feathers) THEN (animal X is a bird) • R2. If (animal X is a bird) and (animal X swims) and (animal X does not fly) and (animal X is black and white) THEN (animal is a penguin) • R3. If (animal X’s mother Z) THEN (animal X Z) • Example: if (animal X’s mother has feathers) • then (animal X has feathers) • R4. If (animal X Z) THEN (animal’s mother Z) • Notes • By combining the facts and rules, we can deduce that Joey is a penguin, and that the Joey’s mother is a penguin. CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Symbolic Pattern Matching • Symbolic pattern matching example • Match F1 with the IF part of R1 • F1. (Joey’s mother has feathers) • R1. If (animal X has feathers) THEN (animal X is a bird) • The expression (Joey’s mother has feathers) matches the pattern (animal X has feathers). • The association (animal X = Joey’s mother) is implied • In general • Symbolic pattern matching • matching an ordinary expression (e.g. fact) to a pattern expression • Unification: more advanced version of pattern matching • match two pattern expressions to see if they can be made identical • Find all substitutions that lead to this CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt
Rule Based Expert System • Rule Based Expert Systems • Once the pattern matching step is done, then we know that Rule R1 can be combined with fact F1 • F1. (Joey’s mother has feathers) • R1. If (animal X has feathers) THEN (animal X is a bird) • The association (animal X = Joey’s mother), along with the second part of the rule (animal X is a bird) leads to a derivedfact: • (Joey’s mother is a bird) CSCI 2210 - Programming in Lisp; Instructor: Alok Mehta; 4.ppt