与cljx有关的目标依赖宏

时间:2015-02-27 00:13:48

标签: clojure clojurescript cljx

问题描述

我有一个项目,通过CLJX同时针对Clojure(JVM)和ClojureScript。

我有一个带有thunk的宏并创建一个IDeref实例,以便在每次取消引用时使用deref@来执行该thunk。

由于它是一个宏,它必须进入 .clj 文件。问题是Clojure和ClojureScript的IDeref接口不同。在Clojure中我需要生成这个:

(reify clojure.lang.IDeref
  (deref [_] thunk))

在ClojureScript中我需要生成这个:

(reify IDeref
  (-deref [_] thunk))

由于这是一个宏,我不能使用cljx中的类似featuer-expression的语法(例如#+cljs -deref)来协调我的两个目标平台的代码。这就是我最终做的事情:

(defmacro make-thunk [exp]
  `(reify ~params/IDeref-interface
     (~params/IDeref-method [_#] ~exp)))

然后我在clj和cljs源树中都有一个单独的 params.clj ,每个源树都有一个def用于每个需要的符号。

这很有效,但它真的很难看,感觉就像是一个肮脏的黑客。

我的问题

我真的想将所有宏保存在同一名称空间中。我宁愿不必在单独的文件中为我的宏定义每个与平台相关的符号。我已经在两个源树中有与平台相关的 compat.clj compat.cljs 文件。必须添加更多文件以支持依赖于平台的宏才开始让事情变得混乱。

这个问题是否有更清洁的解决方案?

2 个答案:

答案 0 :(得分:2)

这应该可以解决问题:

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

像这样使用:

(defmacro foo []
  (if (compiling-cljs?)
    1
    2))

(我觉得这个问题以前已经解决了,但似乎无法找到参考。)

答案 1 :(得分:2)

在宏的主体内部,{C <1}}在ClojureScript中展开时会很简洁,但在Clojure中则不行。

这是目前最好的做法&#34;用于编写特定于平台的宏:

(:ns &env)