280 likes | 289 Views
This course covers advanced topics in AI programming using Lisp, including macros and micros. Topics include the use of macros and micros, extending Lisp with macros, the difference between functions and macros, and the use of backquotes in Lisp.
E N D
“And now for something completely different…” CS251: Intro to AI/Lisp II
Announcements • Web site is coming up • Office hours • Allegro for Windows • Next few weeks • Today and Tuesday: Lisp (Micros/Macros/CLOS) • Thursday: Review of 250/350 final, plan on planning • Tuesday (4/13): Read Chapters 11 & 12 CS251: Intro to AI/Lisp II
Today’s Topics • More Lisp • Macros • Micros CS251: Intro to AI/Lisp II
Micros • “Micros are Lisp runtime objects that have dynamic type resolution and support multiple dispatch, but otherwise do very little.” (Guy Steele) • When should you use micros? • Good when you don’t have much to do • Lots of examples from the reading CS251: Intro to AI/Lisp II
A Quick Quiz • Give two examples where micros are useful • When should you use micros, and when are macros appropriate instead? • Do micros support inheritance? CS251: Intro to AI/Lisp II
Just Kidding April Fools! CS251: Intro to AI/Lisp II
Lisp, Lisp & More Lisp • Common Lisp can do a lot for you, but… … what if you need another language? • Functions just don’t cut it • when is this true? CS251: Intro to AI/Lisp II
Extending Lisp • Lisp is a “programmable programming language” (John Foderaro) • Build your own language with macros • Macros let you treat data as code CS251: Intro to AI/Lisp II
Functions vs. Macros • Evaluate all its arguments • Produce expressions CS251: Intro to AI/Lisp II
How Macros Work • At toplevel, Lisp recognizes macro • Builds the macro expression inline • Evaluates the expression inline CS251: Intro to AI/Lisp II
The defmacro Jam • Use defmacro to create new macros (just like defun) > (defmacro nil! (var) (list `setq var nil)) NIL! CS251: Intro to AI/Lisp II
“Big, Fat, Hairy Deal!” (Garfield) • Everybody and their dog has a macro language • How Lisp works • Parser reads Lisp source, sends its output to the… • Compiler, which compiles it for • Execution • Parser sends a list of Lisp objects CS251: Intro to AI/Lisp II
Macros in the Middle • Macros work between the parser and compiler • Output a list of Lisp objects, so compiler doesn’t notice • An expanding macro has access to all of Lisp Cool, isn’t it? CS251: Intro to AI/Lisp II
Macros, Evaluation and You • Argument evaluation • Remember the quote? > ‘(a b c) (A B C) > (quote (a b c) • Now we’ve got backquote CS251: Intro to AI/Lisp II
Backquote • Backquote lets you control evaluation • Backquote (`) stops evaluation • Comma (,) starts it up again • Comma-at (,@) starts it with a list > (setq a 1 b 2 c 3) 3 > `(a ,b c) ??? > `(a (b ,c)) ??? CS251: Intro to AI/Lisp II
Backquotes & Commas • One comma balances one backquote • Don’t worry unless you have nested backquotes > ‘(a ,(b ,c)) CS251: Intro to AI/Lisp II
Where’s Waldo? • Use defmacro to create new macros (just like defun) • Backquote is used for making lists, but there are other ways > (defmacro nil! (var) (list `setq var nil)) NIL! CS251: Intro to AI/Lisp II
nif With and Without > (defmacro nif (expr pos zero neg) (list ‘case (list ‘truncate (list ‘signum expr)) (list 1 pos) (list 0 zero) (list -1 neg))) > (defmacro nif (expr pos zero neg) `(case (truncate (signum ,expr)) (1 ,pos) (0 ,zero) (-1 ,neg))) CS251: Intro to AI/Lisp II
And the macro expansion is... (nif x ‘p ‘z ‘n) expands into... (case (truncate (signum x)) (1 ‘p) (0 ‘z) (-1 ‘n)) CS251: Intro to AI/Lisp II
Back to the Comma • Turn evaluation back on > (setq b ‘(1 2 3)) (1 2 3) > `(a ,b c) ??? > `(a ,@b c) • Comma-at splices an expression into a list • Insert and remove the ()’s CS251: Intro to AI/Lisp II
When is ,@ Handy? • Macros that take an indeterminate number of arguments • Pass them on to functions or macros that also take an indeterminate number of arguments • Example: Code blocks like progn • Remember when? CS251: Intro to AI/Lisp II
Splicing Away • Doing when our way (defmacro our-when (test &body body) `(if ,test (progn ,@body))) CS251: Intro to AI/Lisp II
Macro Expansion • Why is macro expansion special? > (pprint (macroexpand-1 ‘(our-when (able) (laugh) (laughAgain)))) (if (able) (progn (laugh) (laughAgain))) CS251: Intro to AI/Lisp II
Macro Headaches • Variable capture • Macro variable names collide with the variable names of the expansion context (defmacro ntimes (n &rest body) `(do ((x 0) (+ x 1))) ((>= x ,n)) ,@body)) CS251: Intro to AI/Lisp II
What happens here? > (let ((x 10)) (ntimes 5 (setf x (+ x 1))) x) ??? CS251: Intro to AI/Lisp II
Finding the Problem • Expand the macro (let ((x 10)) (do ((x 0) (+ x 1))) ((>= x 5)) (setf x (+ x 1))) x) (defmacro ntimes (n &rest body) `(do ((x 0) (+ x 1))) ((>= x ,n)) ,@body)) CS251: Intro to AI/Lisp II
A Name to Call Our Own • Generate a new symbol • Use gensym CS251: Intro to AI/Lisp II
A Macro Recipe • Figure out what you’re starting with • Break it down into small chunks • Reassemble the chunks into what you need CS251: Intro to AI/Lisp II