我正在编写一个函数,确定表单(例如(reverse [1 2 3])
)是否为文字。为此,我有以下代码:
(defn literal? [form]
(let [evaluation (try
(eval form)
(catch Exception exception false))]
(if evaluation
(= evaluation form)
true)))
这首先尝试评估表单;如果失败,那么我们认为表格是字面的。
如果表单成功评估,那么我们进一步检查评估是否等于表单本身。如果是这样,那就是文字。
该函数在应用于.clj文件中的[1 2 3]
时有效,但在.cljs文件中,我收到以下错误:
TypeError: Cannot read property 'call' of undefined
at eval (/home/peter/ide/src-cljs/ide/core.cljs[eval16]:71:14)
at eval (native)
at Function.<anonymous> (file:///opt/lighttable-0.8.1-linux/resources/app/core/node_modules/lighttable/bootstrap.js:35236:461)
at b (file:///opt/lighttable-0.8.1-linux/resources/app/core/node_modules/lighttable/bootstrap.js:6188:14)
at a (file:///opt/lighttable-0.8.1-linux/resources/app/core/node_modules/lighttable/bootstrap.js:6234:18)
at cljs.core.do_dispatch (file:///opt/lighttable-0.8.1-linux/resources/app/core/node_modules/lighttable/bootstrap.js:13583:26)
at cljs.core.MultiFn.cljs$core$IMultiFn$_dispatch$arity$2 (file:///opt/lighttable-0.8.1-linux/resources/app/core/node_modules/lighttable/bootstrap.js:13655:32)
at cljs.core._dispatch (file:///opt/lighttable-0.8.1-linux/resources/app/core/node_modules/lighttable/bootstrap.js:13568:14)
at a (file:///opt/lighttable-0.8.1-linux/resources/app/core/node_modules/lighttable/bootstrap.js:13662:32)
at b [as call] (file:///opt/lighttable-0.8.1-linux/resources/app/core/node_modules/lighttable/bootstrap.js:13666:14)
有没有人有一个可以在ClojureScript中使用的解决方案?
提前致谢!
答案 0 :(得分:4)
这是可能的,但这有点棘手!
如果你去clojurescript.io并输入这个神秘的咒语:
(js/cljs.js.eval (js/cljs.js.empty-state) [1 2 3] (fn [x] (prn "********" x)))
然后检查您的开发者控制台,您将看到:
"********" {:value [1 2 3]}
连同出现的其他输出。
希望这能说服你(a)eval有效! (b)eq在cljs中稍微复杂一点。
为什么所有的js互操作你可能会问?在正在执行的REPL的上下文中,这些符号不在编译器的当前状态中,因为javascript是在编译站点时创建的。有预加载状态的方法,但需要一些工作来实现。不要担心,如果您将eval
作为程序的一部分(而不是来自REPL),那么这些都不相关。如果在程序中使用eval,可以编写如下代码:
(ns ....... (:require .....
[cljs.js :refer [eval empty-state js-eval]]))
(eval (empty-state)
[1 2 3]
{:eval js-eval
:source-map true
:context :expr}
(fn [x] (prn "*****" x)))
它产生同样的效果:
"*****" {:value [1 2 3]}
简而言之,您需要从eval
引用cljs.js
,并且需要传递一些州。
以下是一些参考资料,因为......令人困惑,这些都提供了很多细节: