如何将ClojureScript函数序列化到edn,然后反序列化并调用它们?

如何将ClojureScript函数序列化到edn,然后反序列化并调用它们?,clojure,clojurescript,edn,Clojure,Clojurescript,Edn,如果你像这样构造一个字符串 (def s (pr-str {:greet '(partial str "Hello" " " "World!")})) 如何使用读取器(即读取字符串)读取结构,并将:greet键的值作为一个可调用的函数拉回来 请注意,通过引用代码,它保留了形状。如果我删除引号,它将序列化底层javascript函数的核心。我也试过反勾(`) 目标是能够保存用户在某些应用程序中构造的函数,将这些函数序列化到edn,然后反序列化该文本,拉出能够被调用的函数 调用时,上述代码位应返回

如果你像这样构造一个字符串

(def s (pr-str {:greet '(partial str "Hello" " " "World!")}))
如何使用读取器(即
读取字符串
)读取结构,并将
:greet
键的值作为一个可调用的函数拉回来

请注意,通过引用代码,它保留了形状。如果我删除引号,它将序列化底层javascript函数的核心。我也试过反勾(`)

目标是能够保存用户在某些应用程序中构造的函数,将这些函数序列化到edn,然后反序列化该文本,拉出能够被调用的函数

调用时,上述代码位应返回“Hello World!”


安全问题可以单独解决

您可以使用与当前使用的解决方案相同的解决方案,这基本上是可行的

演示: 我准备好了你可以克隆和运行。它包含一个简单的网页,其中有一个可以输入的输入,将对其进行实时评估。代码非常简短,所以应该易于理解并适应您的需要。看起来是这样的:

解决方案 步骤1:获取。它包含我们将使用的
read\u eval\u print
方法。在加载已编译的CLJS文件之前,先将此文件加载到HTML文件中

第2步:由于我们使用的是JS,而不是正确的CLJS依赖项,我们可能需要外部(即在高级编译模式下):

请记住将它们添加到您的
项目.clj

步骤3:
read\u eval\u print
接受两个参数-第一个是带有ClojureScript代码的字符串,第二个是在计算完成后调用的回调。此代码将执行以下操作:

(let [code "(prn ((partial str \"Hello\" \"World\") \" :)\"))"
      cljs (-> js/window .-cljs_bootstrap .-core)]
  (.read_eval_print
    cljs
    code
    (fn [success _] (prn "Success?" success))))
事实上,这很简单,正如你所看到的:

  • cljs
    用于从窗口对象获取
    read\u eval\u print
    方法。这是因为我们将此文件作为普通的JS依赖项导入,而不是CLJS依赖项(这也是我们不需要
    (:require)
    任何内容的原因)
  • 回调函数接受两个参数——第一个参数是布尔标志,如果代码有效并且可以计算,则设置为true;否则设置为false。第二个参数是错误
在浏览器中执行此代码时,会将其打印到JS控制台:

差不多就是这样

几个音符
  • 使用cljs bootstrap作为Clojure依赖项,或者作为Lein依赖项,或者仅仅通过复制所需的名称空间,这将是非常棒的。我这样做并不是因为时间不够。它应该也可以工作,您只需要
    (:require)
    它。不过我没有时间玩它
  • 加载演示页面时,它会显示一些JS加载错误(未找到文件)。这些错误可以忽略。实际上,CLJS编译仍然有效。我还没有对此进行研究

哇。谢谢你在这方面投入了这么多精力。@mario不客气。有趣的问题,解决它很有趣:)
(let [code "(prn ((partial str \"Hello\" \"World\") \" :)\"))"
      cljs (-> js/window .-cljs_bootstrap .-core)]
  (.read_eval_print
    cljs
    code
    (fn [success _] (prn "Success?" success))))