Common Lisp Macros Read for Input Macros Macro lifetime Macro syntax 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 'setq var '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 'setq var 'nil); parameter inserted Becomes (setq var nil)
Macro Example > (setq a 99) ; set a’s value 99 > a ; check value ; 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 > (defmacro cubeit (x) (list (quote *) x x x)) ; (cubeit n) expanded to (* n n n), 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) In a macro body Expands into (+ 1 2 3)
More Macro Examples > (defmacro my-assign (var val) `(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
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
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 >(defmacro alpha (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)
&rest in a Macro &rest works like in a function Note: Recursion > (defmacro let*2 (x &rest forms) (if (null x) `(progn ,@forms) `(let (,(car x)) (let*2 ,(cdr x) ,@forms)))) Note: Recursion