如果你构造一个像这样的字符串
(def s (pr-str {:greet '(partial str "Hello" " " "World!")}))
如何使用阅读器(即read-string
)读取结构并将:greet
键的值作为函数拉回来,而不是可以调用?
请注意,通过引用代码,它会保留形状。如果我删除引号,它会序列化底层javascript函数的内容。我也尝试了反击(`)。
目标是能够保存用户在某个应用程序中构建的函数,将这些函数序列化为edn然后反序列化该文本,拉出能够被调用的函数。
上面的代码应该返回" Hello World!"在被调用时。
安全性可以单独解决。
答案 0 :(得分:3)
您可以使用http://clojurescript.net/正在使用的相同解决方案使其工作 - 基本上是cljs-bootstrap。
我准备了a demo repository你可以克隆并运行。它包含一个简单的网页,其中包含您可以输入的输入,这些输入将进行实时评估。代码非常简短,因此应该易于遵循并适应您的需求。它看起来像这样:
第1步:获取cljs-bootstrap file compiled to JS。它包含我们将使用的read_eval_print
方法。在加载已编译的CLJS文件之前,请在HTML文件中加载此文件。
第2步:由于我们使用JS而不是正确的CLJS依赖项,我们可能需要externs(即在高级编译模式下):
var cljs_bootstrap = {};
cljs_bootstrap.core = {};
cljs_bootstrap.core.read_eval_print = function() {};
请务必将其添加到project.clj
。
第3步: read_eval_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
用于从window对象获取read_eval_print
方法。那是因为我们将这个文件导入为普通的JS依赖,而不是CLJS(这也是我们不需要(:require)
任何东西的原因。此代码在浏览器中执行时,会将其打印到JS控制台:
那就是它。
(:require)
它。虽然我没有时间玩它。