Jump to content

Lisp EN -- Laboratory 6 -- 2006-2007 -- info.uvt.ro

From Wikiversity
Important! These pages are somehow outdated and it is recommended to consult the newer version at Functional programming -- 2008-2009 -- info.uvt.ro (by Ciprian Crăciun).

Lisp EN -- 2006-2007 -- info.uvt.ro


Macros

[edit]

Short introduction to macros

[edit]

Macros -- Wikipedia article


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

ccraciun@info.uvt.ro