180 likes | 310 Vues
Learn about Common Lisp macros, how they differ from functions, the two phases of macro lifetime, macro syntax using backquote and comma, macro expansion examples, and debugging macros. Includes relevant examples and comparisons with functions.
E N D
Common Lisp Macros • Read for Input • Macros • Stored in the same "slot" as a function definition • “special functions” in Lisp • Look just like function calls, • Except – arguments are not evaluated !! • Macro lifetime • expansion and then evaluation • Macro syntax • ` - Backquote : makes them easier to write • , - Comma – evaluate item inside a backquote • ,@ - Splice – splices together inside a backquote • &optional and &rest in argument list • View expansion • with macroexpand-1
Read for Input • The standard function for input is read. • When given no arguments, it reads from the default place, which is usually standard input. • Use in a simple input function (no error checking) >(defun ask (string) (format t "~A " string) (read)) ASK > (ask "How old are you?") How old are you? 29 29
Common Lisp Macros • Lisp programs that write Lisp programs! • defmacro special function • Expanded at compile or load time • Executed at runtime
The Life of Macros • Functions have one important phase • they are applied, i.e. evaluated • Arguments are evaluated, put on stack • Function is applied to arguments • Value is returned • Macros have two phases: 1. expansion and 2. evaluation (of the expansion) – same as a function call
Macro basics • (defmacro nil! (var) (list 'setqvar 'nil)) NIL! Macro arguments are not evaluated at the macro call • Macros expand into Lisp form(s) • Only the final expression of the expansion is evaluated • (list 'setqvar 'nil); parameter inserted • Becomes (setqvar nil)
Macro Example > (setq a 99) ; set a’s value 99 > a; check value 99 ; now call our macro 1. > (nil! a) ; (list 'setq 'a 'nil); expansion 2. The expanded expression is evaluated ; (setq a nil) ; (what happens?) > a; check value again NIL
Create a New Macro >(defmacro mymac (x y z) (list x (list y z))) ; (mymac x y z) expanded to (x (y z)), e.g.: > (mymac car cdr (list 'a 'b 'c)) ; expanded to (car (cdr (list 'a 'b 'c))) B > (defmacrocubeit (x) (list (quote *) x x x)) ; (cubeit n) expanded to (* n nn), e.g.: >(cubeit 3) ; expanded to (* 3 3 3) 27
Backquote Notation • (defmacro nil! (var) ; without backquote (list (quote setq var (quote nil)))) • (defmacro nil! (var) ; shorter with backquote `(setq ,var nil)) • ` backquote specifies template prevents evaluation in expansion • similar to quote in functions • , inside `evaluates the item just after the comma • ,@ inside `evaluates an item and “splices it into” the expression the item should be a list • result is like append
Backquote • Assume(setq a 1 b 2 c 3)
More Macro Examples >(defmacro my-assign (varval) `(setq,var,val)) MY-ASSIGN > (defun assign-test (a b) (my-assign x a) (my-assign y b)) ASSIGN-TEST > (assign-test 3 4) 4 > x 3 > y 4
New IF Macro > (defmacro if2 (a b c) `(cond (,a ,b) (t ,c) ) ) IF2 > (if2 (atom x) (quote yes) (quote no)) YES
defun and defmacro Comparison > (defun head (x) (car x)) HEAD ; function defined > (head (quote (a red table))) A > (defmacro head (x) `(car ,x)) HEAD > (head (quote (a red table))) A
Lecture Question • (defmacro nif (expr pos zero neg) `(case (truncate (signum ,expr)) ( 1 ,pos) ( 0 ,zero) (-1 ,neg))) • 1) What does this macro do? • 2) Write this macro without using a backquote!
Backquote with “splice” ,@ • (setq d (quote (some list))) • `(a ,d b) -> (a (some list) b) • `(a ,@d) -> (a some list) • `(a ,@d b) -> (a some list b) • Look at the macros in www2.hawaii.edu/janst/313/lisp/showout.lisp !
More Macro Expansion Examples > (setq a 3) 3 > '(if a is true (and a a) then) ; regular quote (IF A IS TRUE (AND A A) THEN) >`(if ,a is true ,(and a a) then) ; backquote with , (IF 3 IS TRUE 3 THEN) > (list 'if a 'is 'true (list a a) 'is 'true) ; no backquote (IF 3 IS TRUE (3 3) IS TRUE) > (list 'if a 'is 'true (and a a) 'is 'true) ; no backquote (IF 3 IS TRUE 3 IS TRUE) > (setq b '(a b c)) (A B C) >`(hello fred,b) ; backquote (HELLO FRED (A B C)) >`(hello fred,@b) ; backquote with ,@ (HELLO FRED A B C)
Macro Debugging • macroexpand-1 expands a macro >(defmacroalpha (x y) `(beta ,x ,y)) ALPHA >(macroexpand-1 '(alpha a b)) (BETA A B) T • (defmacro mexp-1 (expr) `(pprint (macroexpand-1 ',expr))) • Note the quote and comma in ',expr • quote ' and comma , • what does that produce?
&optional in a Macro • &optional works like in a function > (defmacro if2 (a b &optional c) `(cond (,a ,b) (t ,c) ) ) IF2 > (if2 (atom x) 'yes 'no) YES > (if2 (atom x) 'yes) YES
&rest in a Macro • &rest works like in a function >(defmacro let*2 (x &rest forms) (if (null x) `(progn ,@forms) `(let (,(car x)) (let*2 ,(cdr x) ,@forms)))) • Note: Recursion