假设我有一个带有 namespace 的库 xx xx.core
,我正在用纯 Clojure 编写它,打算同时针对 Clojure 和 ClojureScript。这样做的实际方法似乎是使用lein-cljsbuild 的交叉和条件注释。到现在为止还挺好。 这个前提现在已经过时了。lein-cljsbuild 已被弃用,取而代之的是reader conditionals,并且还有许多其他命名空间/宏 ClojureScript 增强功能。请参阅下面的更新答案。
假设 xx 有一堆变量,我希望它的用户(无论是在 Clojure 还是 ClojureScript 中)都能够使用。这些可以分为三种类型的变量。
- 宏
- 不依赖 xx 中的宏的函数/其他变量(我将这些称为 type-1 变量)
- 恰好发生的函数/其他变量依赖于 xx 中的宏(我将称这些类型为 2 变量)
.cljs
但是,由于 ClojureScript 要求宏在它们自己的特殊命名空间中与常规命名空间分开.clj
,因此所有宏都必须与xx.core
.
但是其中一些其他 var(type-2 var)的实现偶然地依赖于这些宏!
(可以肯定的是,似乎只有宏可以使用ClojureScriptuse-macro
或require-macro
.xx/core.clj
在 ClojureScript 测试文件中使用(:use-macro xx.core :only […])
. 编译器然后为ClojureScript 文件引用WARNING: Use of undeclared Var
的每个非宏变量发出一条消息。)xx.core
在这种情况下,人们倾向于做什么?在我看来,我唯一能做的就是……将库的公共 API 拆分为三个命名空间:一个用于类型 1 变量,一个用于宏,一个用于类型 2 变量。类似...<code>xx.core, xx.macro
, and xx.util
?...</p>
当然,这很糟糕,因为现在 xx 的任何用户(无论是在 Clojure 还是 ClojureScript 中)都必须知道每个 var(可能有几十个)是否在其实现中碰巧依赖于一个宏,以及它因此而依赖于哪个命名空间属于。如果我只针对 Clojure,这将是不必要的。如果我想同时针对 Clojure 和 ClojureScript,这真的是现在的情况吗?