How to write (simple) macro?
Asked Answered
S

1

5

I need to write a macro (with-hooks (monster method who what) &body body) for a game I'm writing. Monster is a CLOS object, method and who are strings and what is a function (#' notation). The macroexpansion would be something to the effect of

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

I have absolutely no idea how to write such a macro, and I would appreciate some help. I have the creepy feeling that this is easy and I'm a bit ignorant.

Sibyls answered 23/5, 2010 at 16:41 Comment(0)
A
10

I'd write it like this:

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

Some notes:

  1. something-vars are used to ensure that expressions for monster, method, who, what are evaluated only once (because these expressions are referenced multiple times in macro body) and in left-to-right order.
  2. gensyms are used to ensure that variables have guaranteed unique names
  3. unwind-protect is used to ensure that remove-hook is called even in case of non-local exits (e.g., stack unwind due to exception being thrown).
Angleaangler answered 23/5, 2010 at 19:1 Comment(2)
Thank you. I'm working on a GPL roguelike game called Menace of the Mines (motm.sourceforge.net) and just want to make sure this being in there is OK with you. (I have an attributing comment (It's been there for a while))Sibyls
I don't mind if you include this macro in any project in any way.Angleaangler

© 2022 - 2024 — McMap. All rights reserved.