我的目标是创建一个宏,(defdummy MyProtocol MyImplementation)
将创建一个记录类型defrecord
。仅生成MyProtocol
reify
的实现也是可以接受的。此记录类型应实现给定协议的所有方法,但只为每个方法返回nil
。 e.g:
(defprotocol Annoying
(beep [x] "Make a sound"))
;; This form...
(defdummy Annoying FakeAnnoyer)
;; Should expand to this
(defrecord FakeAnnoyer []
Annoying
(beep [x] nil))
我看到当我们评估协议时,我们有一些方法可用于生成协议方法的实现::sigs
,:arglists
等。但是,因为宏接收它们的参数没有评估,我无法从宏内部访问此信息。如果宏用户将协议MyProtocol
传递给我的宏,我只会看到符号'MyProtocol
。在我看来,这些信息在编译时是静态知道的,但我不知道在生成协议方法时是否可以找到它。
我能想到的唯一方法是使用eval
或扩展到defrecord
的某些内部工作方式。还有其他办法吗?
答案 0 :(得分:3)
您可以使用resolve
功能。例如,以下是defdummy
宏的基本实现:
(defmacro defdummy [protocol record]
`(defrecord ~record []
~protocol
~@(for [[_ {:keys [name arglists]}] (:sigs @(resolve protocol))]
`(~name ~@arglists nil))))
示例:
(defprotocol Annoying
(beep [x] "Make a sound"))
(macroexpand-1 '(defdummy Annoying FakeAnnoyer))
;;=> (clojure.core/defrecord FakeAnnoyer [] Annoying (beep [x] nil))