如何在常见的lisp中编写宏定义宏

时间:2010-06-25 20:14:49

标签: macros lisp common-lisp

我的代码库中有两个宏(和攀爬),如下所示:

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

和此:

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

每个宏都具有以下调用语法:(def-stat-method ranged-weapon :ranged-weapon)

我希望宏(def-foo-method macro-name method)扩展为适当的宏,以便(def-foo-method def-stat-method stats)扩展为上面的第一个示例。我是一个口齿不清的新手,并不知道该怎么做。所有帮助表示赞赏。

2 个答案:

答案 0 :(得分:13)

只需编写一个扩展为另一个defmacro的宏,如下所示:

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

我认为没有let可能有办法做到这一点,但嵌套的反引号令人困惑:)

答案 1 :(得分:2)

对我而言,代码看起来很慢。面向对象的运行时调度加上属性列表的搜索?为什么呢?

有时,属性列表会添加到CLOS对象中,以便为不常用的插槽提供存储,或者使它们易于扩展(在运行程序之前可以添加所有类型的属性而不需要知道所有属性)。通常,最好使属性成为对象的实际插槽。