Target-dependent macros with cljx
问题描述
我有一个通过CLJX面向Clojure(JVM)和ClojureScript的项目。
我有一个接受thunk的宏,并创建一个
由于它是一个宏,因此必须放入.clj文件中。问题是
1 2 | (reify clojure.lang.IDeref (deref [_] thunk)) |
在ClojureScript中,我需要生成以下代码:
1 2 | (reify IDeref (-deref [_] thunk)) |
由于这是一个宏,因此我无法使用cljx中类似featuer-expression的语法(例如
1 2 3 | (defmacro make-thunk [exp] `(reify ~params/IDeref-interface (~params/IDeref-method [_#] ~exp))) |
然后,我在clj和cljs源代码树中都有一个单独的params.clj,每个树中每个需要的符号都有一个
这行得通,但确实很丑陋,感觉就像是肮脏的骇客。
我的问题
我真的很想将所有宏都保留在相同的名称空间中。我宁愿不必在单独的文件中为宏定义每个与平台相关的符号。我已经在两个源代码树中有了依赖于平台的compat.clj和compat.cljs文件。必须添加更多文件以支持依赖于平台的宏开始使事情变得混乱。
有没有更清洁的解决方案来解决这个问题?
在宏主体内部,在ClojureScript中而不在Clojure中扩展时,
当前,这是编写特定于平台的宏的"最佳实践":
1 2 3 4 | (defmacro platform [] (if (:ns &env) :CLJS :CLJ)) |
这应该可以解决问题:
1 2 3 4 5 6 7 8 9 | (defn compiling-cljs? "Returns true if we seem to be compiling ClojureScript, false otherwise. This is a Clojure function, meant to be called by macros targeting both Clojure and ClojureScript." [] (if-let [cljs-ns-var (resolve 'cljs.analyzer/*cljs-ns*)] (some? @cljs-ns-var) false)) |
像这样使用:
1 2 3 4 | (defmacro foo [] (if (compiling-cljs?) 1 2)) |
(我觉得这个问题以前已经解决过,但似乎找不到参考。)