首页 > 解决方案 > 使用宏动态生成 reify 子句

问题描述

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

例如:

我想生成:

(reify
  BaseInterface
    (fee [_] (custom-operation wrapped))
    (foo [_] (.foo wrapped)))

或者

(reify
  BaseInterface
    (fee [_] (custom-operation wrapped))
    (foo [_] (.foo wrapped))
  AnotherInterface
    (bar [_] (.bar wrapped)))

取决于是wrapped只实现BaseInterface还是两者兼而有之BaseInterfaceAnotherInterface

我尝试了类似以下的方法,但它失败了,因为宏在编译时被评估并且我的第二个参数(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 分支,因为一旦我有更多接口,它就会导致组合爆炸。

标签: clojurereify

解决方案


推荐阅读