Как написать (простой) макрос? - PullRequest
5 голосов
/ 23 мая 2010

Мне нужно написать макрос (with-hooks (monster method who what) &body body) для игры, которую я пишу. Monster - это объект, метод CLOS, кто такие строки и что такое функция (обозначение #). Макрораспространение будет что-то с эффектом

(add-hook monster method who what)
,@body
(remove-hook monster method who)

Я абсолютно не знаю, как написать такой макрос, и я был бы признателен за помощь. У меня такое жуткое ощущение, что это легко, и я немного невежественен.

1 Ответ

10 голосов
/ 23 мая 2010

Я бы написал так:

(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)))))

Некоторые примечания:

  1. something-var s используются для того, чтобы выражения для monster, method, who, what вычисляются только один раз (поскольку на эти выражения ссылаются несколько раз в теле макроса) и в порядке слева направо.
  2. gensym s используются для обеспечения того, что переменные имеютгарантированные уникальные имена
  3. unwind-protect используется, чтобы гарантировать, что remove-hook вызывается даже в случае нелокальных выходов (например, разматывание стека из-за создаваемого исключения).
...