Как написать (простой) макрос?
-
04-10-2019 - |
Вопрос
Мне нужно написать макрос (with-hooks (monster method who what) &body body)
Для игры я пишу. Monster - это закрытый объект, метод и кто являются строками, и что такое функция (# «нотация). Macroexpansion будет чем-то для эффекта
(add-hook monster method who what)
,@body
(remove-hook monster method who)
у меня есть абсолютно Не имею, как написать такой макрос, и я был бы признателен за помощь. У меня жуткое чувство, что это легко, и я немного невежественнее.
Решение
Я бы написал это так:
(defmacro with-hooks ((monster method who what) &body body)
(let ((monster-var (gensym))
(method-var (gensym))
(who-var (gensym))
(what-var (gensym)))
`(let ((,monster-var ,monster) ; dummy comment
(,method-var ,method)
(,who-var ,who)
(,what-var ,what))
(add-hook ,monster-var ,method-var ,who-var ,what-var)
(unwind-protect
(progn ,@body)
(remove-hook ,monster-var ,method-var ,who-var)))))
Некоторые заметки:
something-var
s используются для обеспечения того, чтобы выражения дляmonster
,method
,who
,what
оцениваются только один раз (потому что эти выражения ссылаются несколько времен в корпусе макроса) и в порядке лево-правильного.gensym
S используются для обеспечения того, чтобы переменные были гарантированы уникальные имена- Отдожди защита используется для обеспечения того, чтобы
remove-hook
называется даже в случае не локальных выходов (например, стека, расслабиться из-за брошенного исключения).
Не связан с StackOverflow