Dans une application de type Emacs, on souhaite écrire une macro permettant de définir une fonction interactive (c'est-à-dire, pouvant être appelée par l'utilisateur de l'application). Pour cela on souhaite rajouter à la syntaxe de defun la possibilité de préciser comment obtenir les arguments interactivement. On souhaite par exemple pouvoir écrire :
(defun-inter mail-file-to ((filename (minibuffer-read-file))
(to (minibuffer-read-string))
(signature (numeric-argument)))
...
...)
Le résultat d'un tel appel doit donner les deux effets suivants. D'abord une fonction mail-file-to doit être définie, comme si on avait écrit :
(defun mail-file-to (filename to signature)
...
...)
puis une entrée doit être définie dans la liste de propriétés du symbole mail-file-to contenant une fonction anonyme définie avec :
(setf (get 'mail-file-to 'interactive
#'(lambda () (mail-file-to (minibuffer-read-file)
(minibuffer-read-string)
(numeric-argument)))))
Pour que les deux résultats soient obtenus simultanément, la macro doit en réalité générer :
(progn
(defun mail-file-to (filename to signature)
...
...)
(setf (get 'mail-file-to 'interactive
#'(lambda () (mail-file-to (minibuffer-read-file)
(minibuffer-read-string)
(numeric-argument))))))
Voici une solution possible :
(defmacro defun-inter (name arglist &body body)
`(progn
(defun ,name ,(mapcar #'car arglist)
,@body)
(setf (get ',name 'interactive
#'(lambda ()
(,name ,@(mapcar #'cadr arglist)))))))