Lisp EN -- Laboratory 6 -- 2006-2007 -- info.uvt.ro
Lisp EN -- 2006-2007 -- info.uvt.ro
- Lisp EN -- Laboratory 1 -- 2006-2007 -- info.uvt.ro
- Lisp EN -- Laboratory 2 -- 2006-2007 -- info.uvt.ro
- Lisp EN -- Laboratory 3 -- 2006-2007 -- info.uvt.ro
- Lisp EN -- Laboratory 4 -- 2006-2007 -- info.uvt.ro
- Lisp EN -- Laboratory 5 -- 2006-2007 -- info.uvt.ro
- Lisp EN -- Laboratory 6 -- 2006-2007 -- info.uvt.ro
- Lisp EN -- Laboratory 7 -- 2006-2007 -- info.uvt.ro
- Lisp EN -- Test -- 2006-2007 -- info.uvt.ro
Macros
[edit]Short introduction to macros
[edit]
The two functions are used to see the macro-expansion of a given code. The difference between the two is that macroexpand expands as many times as there is a macro in the resulting code, meanwhile macroexpand-1 expands the code only once, thus allowing us to see the behavior step-by-step.
(macroexpand <code_>) ;=> <expanded-code> (macroexpand-1 <code_>) ;=> <expanded-code>
(macroexpand '(and a b c)) ;=> (if (not a) nil (if (not b) nil c)) (macroexpand '(or a b c)) ;=> (if a a (if b b c)) (macroexpand '(cond (a a) (b b))) ;=> (if a a (if b b nil)) (macroexpand '(cond (1 1) (2 2))) ;=> 1
(macroexpand-1 '(and a b c)) ;=> (cond ((not a) nil) ((not b) nil) (t c)) (macroexpand-1 '(or a b c)) ;=> (cond (a) (b) (t c)) (macroexpand-1 '(cond (a a) (b b))) ;=> (if a a (if b b nil)) (macroexpand-1 '(cond (1 1) (2 2))) ;=> 1
Difference between "'", "`", ",", and ",@"
[edit](setq a 1 b 2 c 3) '(a b c) ;=> (a b c) `(a b c) ;=> (a b c) `(a ,b c) ;=> (a 2 c) `(a (,b c)) ;=> (a (2 c)) `(a ',(+ a b c)) ;=> (a '6)
(setq l '(a b c)) '(1 l) ;=> (1 l) `(1 l) ;=> (1 l) `(1 ,l) ;=> (1 (a b c)) `(1 ,@l) ;=> (1 a b c)
(setq l '(1 2 3)) `(+ ,@l) ;=> (+ 1 2 3) (eval `(+ ,@l)) ;=> 6
defmacro is used -- as it's name suggests -- to define a macro. In Lisp a macro is nothing else than a normal function which is called when the code is parsed (at compile-time, not at run-time).
(defmacro <name> (<argument-1> ... <argument-n>) <generating-statements>)
(defmacro variabila (nume valoare) (list 'setq nume valoare)) (defmacro variabila (nume valoare) `(setq ,nume ,valoare)) (macroexpand '(var a 1)) => (setq a 1)
Wrong:
(defmacro my-dotimes (n &rest statements) `(do ((x 0 (+ x 1))) ((>= x ,n)) ,@statements))
Right:
(defmacro my-dotimes (n &rest statements) (let ((g (gensym)) (h (gensym))) `(do ((,h ,n) (,g 0 (+ ,g 1))) ((>= ,g ,h)) ,@statements)))
Exercises
[edit]- my-and (for two arguments)
- my-or (for two arguments)
- my-swap
- my-when
- my-unless
- my-while
- my-dotimes
- my-dolist
- my-and (for n arguments)
- my-or (for n arguments)
Assignment 6
[edit]This assignment is due next Wednesday (2007-04-18) at 24:00, and should be sent by email.
When you send the email please include in the subject [LISP-EN-2] First_name Last_name for the second year and [LISP-EN-3] First_name Last_name for the third year. Please paste the code inside the email, DO NOT ATTACH any files.
The assignment for next week is to implement 6 complex (not simple) macros, (also use gensym), and then for each 3 examples on how the macro will expand for a given set of arguments (you can use macroexpand-1).
Ciprian Dorin Craciun
2007-04-13