180 likes | 289 Views
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
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