Я бы написал так:
(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 используются для обеспечения того, что переменные имеютгарантированные уникальные имена - unwind-protect используется, чтобы гарантировать, что
remove-hook
вызывается даже в случае нелокальных выходов (например, разматывание стека из-за создаваемого исключения).