你好!我一直在一个 future
中使用 clojure.tools.build.api
的一些函数,并且偶尔会看到以下错误...
Execution error (IllegalStateException) at clojure.tools.build.api/create-basis (api.clj:154).
Attempting to call unbound fn: #'clojure.tools.build.tasks.create-basis/create-basis
正如我在 tools.build 中看到的那样...
(defn create-basis
([]
((requiring-resolve 'clojure.tools.build.tasks.create-basis/create-basis)))
([params]
((requiring-resolve 'clojure.tools.build.tasks.create-basis/create-basis) params)))
...代码实际上仅使用 requiring-resolve
来执行另一个函数。深入研究 requiring-resolve
,我可以看到第一次调用 resolve
没有与 serialized-require
函数使用的相同锁进行同步...
(defn- serialized-require
[& args]
(locking clojure.lang.RT/REQUIRE_LOCK
(apply require args)))
(defn requiring-resolve
[sym]
(if (qualified-symbol? sym)
(or (resolve sym)
(do (-> sym namespace symbol serialized-require)
(resolve sym)))
(throw (IllegalArgumentException. (str "Not a qualified symbol: " sym)))))
首先,当其他线程正在通过 serialized-require
过程中加载该命名空间时,requiring-resolve
是否实际上在第一次调用 resolve
时返回 clojure.lang.Var$Unbound
?假设如此,那么 tools.build
(以及我想扩展到大多数 Clojure 代码)应避免使用 ((requiring-resolve 'some-other/function))
模式?requiring-resolve
是否可以被修改为线程安全?
谢谢!