Clojure 使用宏动态生成具体化子句
我正在尝试包装一个实现,并为包装对象实现的所有接口动态生成reify子句 例如: 我想生成:Clojure 使用宏动态生成具体化子句,clojure,reify,Clojure,Reify,我正在尝试包装一个实现,并为包装对象实现的所有接口动态生成reify子句 例如: 我想生成: (reify BaseInterface (fee [_] (custom-operation wrapped)) (foo [_] (.foo wrapped))) 或 取决于wrapped是仅实现BaseInterface还是同时实现BaseInterface和AnotherInterface 我尝试了以下方法,但失败了,因为宏是在编译时计算的,我的第二个参数(cond->表达
(reify
BaseInterface
(fee [_] (custom-operation wrapped))
(foo [_] (.foo wrapped)))
或
取决于wrapped
是仅实现BaseInterface
还是同时实现BaseInterface
和AnotherInterface
我尝试了以下方法,但失败了,因为宏是在编译时计算的,我的第二个参数(cond->表达式)没有运行时值:
(defmacro add-interface-implementations
"Adds additional interface implementations to a reify expression.
This is useful to create a reify expression dynamically without introducing if-else branching."
[reify-expr interface->methods]
(reduce
(fn [expr# entry#]
(println "expr#" expr#)
(println "entry#" entry#)
(let [[interface# body#] entry#]
(cons
(first expr#)
(cons interface#
(reduce
(fn [e# m#]
(cons m# e#))
(rest expr#)
body#)))))
reify-expr
interface->methods))
(add-interface-implementations
(reify
BaseInterface
(fee [_] (custom-operation wrapped))
(foo [_] (.foo wrapped)))
(cond-> {}
(instance? AnotherInterface foo)
(assoc AnotherInterface [(bar [_] (.bar wrapped))])))
关于如何实现我正在尝试的目标的任何建议。我希望避免if-else分支,因为一旦我有了更多接口,它就会导致组合爆炸。您可以传入一个可能的接口列表,然后在循环中使用
(isa?子-父)
,只保留所需的接口。然后,构造具体化命令。但是,由于在运行时之前没有包装
或构造具体化
命令,因此我认为您必须使用eval
。可能是个坏兆头。为什么要这样做?我正在为一个对象创建一个包装器来覆盖某些方法。为了保持相同的行为,我需要实现包装对象实现的所有接口。但似乎您必须事先知道覆盖的是哪些方法,对吗?使用更现实的示例目标而不是wrapped
,用例可能更清晰。我用一个被覆盖的fee
方法更新了示例。其他方法只需要根据包装的
实现的任何接口进行委派。您可以传入一个可能的接口列表,然后在循环中使用(isa?子-父)
,以仅保留所需的接口。然后,构造具体化命令。但是,由于在运行时之前没有包装
或构造具体化
命令,因此我认为您必须使用eval
。可能是个坏兆头。为什么要这样做?我正在为一个对象创建一个包装器来覆盖某些方法。为了保持相同的行为,我需要实现包装对象实现的所有接口。但似乎您必须事先知道覆盖的是哪些方法,对吗?使用更现实的示例目标而不是wrapped
,用例可能更清晰。我用一个被覆盖的fee
方法更新了示例。其他方法只需要根据wrapped
实现的接口进行委派。
(defmacro add-interface-implementations
"Adds additional interface implementations to a reify expression.
This is useful to create a reify expression dynamically without introducing if-else branching."
[reify-expr interface->methods]
(reduce
(fn [expr# entry#]
(println "expr#" expr#)
(println "entry#" entry#)
(let [[interface# body#] entry#]
(cons
(first expr#)
(cons interface#
(reduce
(fn [e# m#]
(cons m# e#))
(rest expr#)
body#)))))
reify-expr
interface->methods))
(add-interface-implementations
(reify
BaseInterface
(fee [_] (custom-operation wrapped))
(foo [_] (.foo wrapped)))
(cond-> {}
(instance? AnotherInterface foo)
(assoc AnotherInterface [(bar [_] (.bar wrapped))])))