问题描述
我有一个通过 CLJX 同时针对 Clojure (JVM) 和 ClojureScript 的项目。
我有一个宏,它接受一个 thunk 并创建一个IDeref
实例以在每次取消引用时执行该 thunk(使用deref
or @
)。
因为它是一个宏,所以它必须放在一个.clj文件中。问题是IDeref
Clojure 和 ClojureScript 的接口不同。在 Clojure 我需要生成这个:
(reify clojure.lang.IDeref
(deref [_] thunk))
在 ClojureScript 中,我需要生成这个:
(reify IDeref
(-deref [_] thunk))
由于这是一个宏,我不能使用 cljx(例如#+cljs -deref
)中的类似特征表达式的语法来协调我的两个目标平台的代码。这就是我最终做的事情:
(defmacro make-thunk [exp]
`(reify ~params/IDeref-interface
(~params/IDeref-method [_#] ~exp)))
然后,我在 clj 和 cljs 源代码树中都有一个单独的params.clj,每个源代码树都有一个def
用于每个需要的符号。
这行得通,但它真的很难看,感觉就像一个肮脏的黑客。
我的问题
我真的很想把我所有的宏都放在同一个命名空间中。我宁愿不必在单独的文件中为我的宏定义每个平台相关的符号。我已经在两个源代码树中有平台相关的compat.clj和compat.cljs文件。必须添加更多文件来支持依赖于平台的宏开始让事情变得混乱。
这个问题有更清洁的解决方案吗?