这是一个非常奇怪的案例!
当我调用我的宏时,我已经达到了defrecord定义,但我只获得了没有评估的代码。
(defmacro protocol-impl [protocol-definition]
``(defrecord ~(symbol "my-wrapper") [~(symbol "e#")]
~@(let [[type# protocol-functions#] ~protocol-definition]
(conj
(map
(fn [[function-name# function-args#]]
`(~function-name# ~function-args#
(~function-name# ~(symbol "e#") ~@(next function-args#))))
protocol-functions#) type#))
))
(protocol-impl (adapt-super-impls (first (get-methods (Example.)))))
;;=> (clojure.core/defrecord
;; my-wrapper
;; [e#]
;; wrapper.core.Welcome
;; (say_bye [this# a# b#] (say_bye e# a# b#))
;; (greetings [this#] (greetings e#)))
如果我尝试
(my-wrapper. (Example.))
=> Unable to resolve classname: my-wrapper
但如果我在nrepl中评估我的宏调用生成的输出,那么defrecord就会被评估为
任何让这个宏工作的想法,或者我如何使用当前的宏输出?
here the gist with 70 lines of code
提前致谢 涓
PS:我知道这个双重``导致了这种行为,但是为了定义一个defrecord你需要所有协议和fns遵循相同的列表定义,我没有找到更好的方法来实现它答案 0 :(得分:0)
好的,我看了一下你的要点中的一些代码,至少足以理解它们正在做什么。不可否认,你的protocol-impl
宏的内部工作方式让我感到困惑,特别是所有额外的后退,在我看来,通过使用这样的一般结构,你的代码可以通过重构来减少混淆: / p>
(defmacro foo [bar]
(let [baz (symbol (some calculation here))
quux (map some-fn (take 2 some-collection))]
`(do stuff with ~baz and ~quux)))
(let
绑定中的实际值只是任意伪代码;这里的想法只是为了避免在宏定义中出现大量引用和取消引用,将一些计算拖入{ {1}}绑定,甚至是宏定义之外的单独函数)
但是抛开这个问题,这将解决您返回let
表单而不是eval'd的问题:
defrecord
那么为什么这样做而不是这个?
(defmacro protocol-impl [protocol-definition]
`(eval
`(defrecord ... etc.
(protocol-impl '[wrapper.core.Welcome
([say_bye [this a b]]
[greetings [this]])])
(my-wrapper. (Example.))
;=> #wrapper.core.my-wrapper{:e# #wrapper.core.Example{}}
我完全不知道。据说它与在语法引用形式之外使用非引号((defmacro protocol-impl [protocol-definition]
`(defrecord ... etc.
(protocol-impl '[wrapper.core.Welcome
([say_bye [this a b]]
[greetings [this]])])
;=> Exception in thread "main" java.lang.IllegalStateException:
;=> Attempting to call unbound fn: #'clojure.core/unquote ...
)有关,但我不明白如果整个宏定义包含在语法引用中,那怎么可能...... / p>