你好!我一直在 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 该命名空间时,requiring-resolve
是否有可能从第一个 resolve
调用返回 clojure.lang.Var$Unbound
?假设是这样,tools.build
(我认为扩展到大多数 Clojure 代码)应该避免使用 ((requiring-resolve 'some-other/function))
模式吗?requiring-resolve
是否可以修改为线程安全?
谢谢!