Clojure 使用宏动态生成具体化子句

Clojure 使用宏动态生成具体化子句,clojure,reify,Clojure,Reify,我正在尝试包装一个实现,并为包装对象实现的所有接口动态生成reify子句 例如: 我想生成: (reify BaseInterface (fee [_] (custom-operation wrapped)) (foo [_] (.foo wrapped))) 或 取决于wrapped是仅实现BaseInterface还是同时实现BaseInterface和AnotherInterface 我尝试了以下方法,但失败了,因为宏是在编译时计算的,我的第二个参数(cond->表达

我正在尝试包装一个实现,并为包装对象实现的所有接口动态生成reify子句

例如:

我想生成:

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