Динамическое создание предложения reify с использованием макросов - PullRequest
1 голос
/ 11 июня 2019

Я пытаюсь обернуть реализацию и динамически сгенерировать предложение 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 или оба 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, так как оно приведет к комбинаторному взрыву, как только у меня будет больше интерфейсов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...