问题描述
我有一个通过ClojureScript以CLJX为目标的项目。
我有一个宏,它接受一个thunk,并创建一个IDeref实例来在每次取消引用(使用deref或@)时执行该thunk。
因为它是一个宏,所以它必须放在一个.clj文件中。问题是,对于Clojure和ClojureScript,IDeref接口是不同的。在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文件。不得不添加更多的文件来支持平台相关的宏开始让人感到混乱。
这个问题有更干净的解决办法吗?
发布于 2015-02-27 07:08:13
在宏的主体中,(:ns &env)在ClojureScript中展开时是真实的,而在Clojure中则不然。
这是目前编写特定于平台的宏的“最佳实践”:
(defmacro platform []
(if (:ns &env)
:CLJS
:CLJ))发布于 2015-02-27 00:48:29
这应该能起作用:
(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))(我有一种感觉,这个问题以前已经解决了,但似乎找不到参考。)
https://stackoverflow.com/questions/28755294
复制相似问题