如何使函数可用于 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 函数关联的变量:
x
的编译器分析元数据需要存在于作为第一个参数传递给 cljs.js/eval
的状态中。这样一来,在编译期间,诸如 x
的数量之类的东西就可以知道了,例如。
- 与
x
关联的函数的 JavaScript 实现需要出现在 JavaScript 运行时中。 (如果函数在 cljs.js/eval
调用期间实际上被 调用 而不仅仅是引用,则尤其如此。)
如果x
是核心函数(比如var #'cljs.core/map
),那么这两个条件都会自动满足。特别是,元数据将在 cljs.js/empty-state
被调用时产生(假设 :dump-core
是 true
),并且核心功能的实现已经加载到 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!
函数作为此用例的帮助程序存在,一个独立的示例位于
在 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 函数关联的变量:
x
的编译器分析元数据需要存在于作为第一个参数传递给cljs.js/eval
的状态中。这样一来,在编译期间,诸如x
的数量之类的东西就可以知道了,例如。- 与
x
关联的函数的 JavaScript 实现需要出现在 JavaScript 运行时中。 (如果函数在cljs.js/eval
调用期间实际上被 调用 而不仅仅是引用,则尤其如此。)
如果x
是核心函数(比如var #'cljs.core/map
),那么这两个条件都会自动满足。特别是,元数据将在 cljs.js/empty-state
被调用时产生(假设 :dump-core
是 true
),并且核心功能的实现已经加载到 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!
函数作为此用例的帮助程序存在,一个独立的示例位于