Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I write a macro-defining macro in common lisp

I have about two macros (and climbing) in my codebase that look like this:

(defmacro def-stat-method (method-name stat)
  `(progn
     (defmethod ,method-name ((monster monster))
       (getf (stats monster) ,stat))
     (defmethod (setf ,method-name) (value (monster monster))
       (setf (getf (stats monster) ,stat) value))))

and this:

(defmacro def-energy-method (method-name stat)
  `(progn
     (defmethod ,method-name ((monster monster))
       (getf (energies monster) ,stat))
     (defmethod (setf ,method-name) (value (monster monster))
       (setf (getf (energies monster) ,stat) value))))

Each of the macros has the following calling syntax: (def-stat-method ranged-weapon :ranged-weapon)

I would like a macro (def-foo-method macro-name method) that expands into the appropriate macros so that (def-foo-method def-stat-method stats) expands into the first example above. I am a lisp newbie and don't really know how to do this. All help appreciated.

like image 222
krzysz00 Avatar asked Jun 25 '10 20:06

krzysz00


1 Answers

Just write a macro that expands into another defmacro, like this:

(defmacro def-foo-method (macro-name method)
  `(defmacro ,macro-name (method-name stat)
     (let ((method ',method))
       `(progn
          (defmethod ,method-name ((monster monster))
            (getf (,method monster) ,stat))
          (defmethod (setf ,method-name) (value (monster monster))
            (setf (getf (,method monster) ,stat) value))))))

I think there might be a way to do this without the let, but nested backticks are confusing :)

like image 65
wdebeaum Avatar answered Oct 30 '22 02:10

wdebeaum