Parfois, on souhaite évaluer une suite d'expressions dans un contexte temporaire dont la création dépend de l'application. Par exemple, dans une application de manipulation de formes géométriques, on souhaite parfois créer un contexte à partir d'une forme. Au lieu d'écrire :
(let ((x1 (point-x (line-start line)))
(y1 (point-y (line-start line)))
(x2 (point-x (line-end line)))
(y2 (point-y (line-end line))))
expression-1
...
expression-n)
on souhaite pouvoir écrire :
(with-line (x1 x2 y1 y2) line
expression-1
...
expression-n)
On peut envisager la macro suivante :
(defmacro with-line ((xs ys xe ye) line &body body)
`(let ((,xs (point-x (line-start ,line)))
(,ys (point-y (line-start ,line)))
(,xe (point-x (line-end ,line)))
(,ye (point-y (line-end ,line))))
,@body))
On remarque ici une fonctionnalité supplémentaire concernant la lambda-liste d'une macro. A la place d'un paramètre ordinaire, on trouve une liste de paramètres. Ceci permet une destructuration automatique de l'argument de la macro.
* (macroexpand-1 '(with-line (x y z t) line body))
(LET ((X (POINT-X (LINE-START LINE)))
(Y (POINT-Y (LINE-START LINE)))
(Z (POINT-X (LINE-END LINE)))
(T (POINT-Y (LINE-END LINE))))
BODY)
T
*