如何使函数可用于 ClojureScript 的 eval?

How can I make functions available to ClojureScript's eval?

this blog post by Dmitri Sotnikov 中,为 运行 包含 ClojureScript 的字符串提供了一个函数 eval-str

(defn eval-str [s]
  (eval (empty-state)
        (read-string s)
        {:eval       js-eval
         :source-map true
         :context    :expr}
        (fn [result] result)))

如果我有一些函数 x 我希望能够从 eval 字符串内部调用,我该怎么做?

答案分为两部分,假设 x 是与 ClojureScript 函数关联的变量:

  1. x 的编译器分析元数据需要存在于作为第一个参数传递给 cljs.js/eval 的状态中。这样一来,在编译期间,诸如 x 的数量之类的东西就可以知道了,例如。
  2. x 关联的函数的 JavaScript 实现需要出现在 JavaScript 运行时中。 (如果函数在 cljs.js/eval 调用期间实际上被 调用 而不仅仅是引用,则尤其如此。)

如果x是核心函数(比如var #'cljs.core/map),那么这两个条件都会自动满足。特别是,元数据将在 cljs.js/empty-state 被调用时产生(假设 :dump-coretrue),并且核心功能的实现已经加载到 JavaScript运行时。

但是,假设 x 是您希望在自托管环境中编译的全新函数。 “技巧”是设置和重用编译器状态:例如,将 (cljs.js.empty-state) 的结果放入 var,并将其传递给每个 cljs.js/eval 调用。如果您这样做,并且其中一个 cljs.js/eval 调用涉及为 x 编译 defn,则编译器状态将为 modified(它是实际上是一个原子),结果是 x 的编译器元数据将被放入状态,当然,x 的 JavaScript 实现被设置在 JavaScript 环境(通过评估为 defn 生成的 JavaScript)。

另一方面,如果 x 是属于“环境”ClojureScript 环境的一部分的函数(例如,通过 JVM ClojureScript 编译器预编译,但仍然可以在 JavaScript 运行时),然后由您以某种方式安排让 x 的编译器分析元数据进入传递给 cljs.js/eval 的状态。如果您查看基于 JVM 的编译器的输出,您将看到包含此​​类元数据的 <ns-name>.cache.json 个文件。查看这些文件中的数据,您可以确定其结构;有了它,您可以看到如何将所需信息交换到 [:cljs.analyzer/namespaces <ns-name>] 下的编译器状态。 cljs.js/load-analysis-cache! 函数作为此用例的帮助程序存在,一个独立的示例位于