javascript - 在ClojureScript中使用 'eval'特殊形式来判断一个形式是否是文字

标签 javascript clojure clojurescript

我正在编写一个确定表单是否(例如(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 的解决方案?

提前致谢!

最佳答案

这是可能的,但有点棘手!

如果你去 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) eval 在 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]}

简而言之,您需要从 cljs.js 引用 eval,并且它需要传递一些状态。

这里有一些引用,因为...它很困惑,但这些提供了很好的细节:

  1. http://clojurescript.io/查看构建此站点的代码。
  2. 阅读 Mike Fikes 的博客! https://blog.fikesfarm.com/posts/2016-01-22-clojurescript-eval.html (和其他帖子)他编写了大部分自举代码并在 Planck 中积极使用它。
  3. https://yogthos.net/posts/2015-11-12-ClojureScript-Eval.html
  4. http://ctford.github.io/klangmeister/预加载状态的重要引用。

关于javascript - 在ClojureScript中使用 'eval'特殊形式来判断一个形式是否是文字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38087493/

相关文章:

clojure - 在 Clojure 中声明匿名函数是否很昂贵?

clojure - 在 Common Lisp 中调用函数列表

clojure - 字符的序数/int/ascii 值

clojure - 使用 clojurescript 包装 knockout.js

javascript - 在 JavaScript DOM 中从父节点拆分节点

clojure 不连续的让

macos - Clojure 跷跷板应用程序 : How to change menubar title from "main"

javascript - 使用 cookies 只显示我的弹出窗口一次?

javascript - meteor 动态下拉菜单不起作用

javascript - 如何获得关于 on click 语句的 return 和 end 的正确引用?