ClojureScript等效于此JavaScript代码

时间:2017-02-23 17:06:43

标签: javascript clojurescript

我正在尝试在我的ClojureScript代码中使用esrecurse,我有一个看起来像这样的JavaScript代码片段

esrecurse.visit(ast, {
  Literal: console.log
});

我正在努力想出ClojureScript的等价物,但每当我运行它esrecurse.visit时都不会被称为

#(.visit esrecurse % (js-obj "Literal" (fn [node] node)))

其中%是AST。老实说,我不确定我做错了什么,我也试过以不同的方式传递第二个参数,比如

#(.visit esrecurse (first (vals %)) {:Literal (fn [node] node)})

没有成功。

我正在调用此{/ 1}}

mutate?

但是对于这个版本和我的版本我仍然没有得到任何东西,我也尝试传递(defn mutate? "applies a mutation to the ASTs, returns the mutated, or non mutated, ASTs" [asts] (map #(.visit esrecurse % #js {:Literal print}) asts)) (mutate? (reader/to-ast (reader/read "./test/example-project/lib"))) 而不是identity,但我得到print作为结果。

1 个答案:

答案 0 :(得分:1)

对于我来说,esrecurse.visit

的模拟实现对我来说很好
(defn visit [ast]
  (.visit esrecurse ast #js {:Literal print}))

(visit #js {:type "Literal"})

;; prints #js {:type "Literal"}

模拟代码:

var esrecurse = {
  visit(node, visitor) {
    visitor.Literal(node);
  }
}

这是同一个想法的一个不那么冗长的版本。

 #(.visit esrecurse % #js {:Literal print}))

验证您是否正确调用了该函数,因为您的第一个实现对我来说很合适并且可以替代上述任一函数。

猜测一下,我说你在第二个例子中没有看到任何事情的原因是因为Clojure的序列是 lazy - 意味着你的计算赢了&直到你要求结果才会被应用。

这些懒惰的序列(take也返回一个)仅在某些内容调用doalldorundoseq时进行评估。

如果您调用print或评估在repl中返回延迟序列的表达式,则会发生这种情况。

您可以尝试使用doall强制评估您的懒惰表达式。

(doall
  (mutate? (reader/to-ast (reader/read "./test/example-project/lib"))))

这并不自然,这是重点。作为一种相当纯粹的函数式编程语言,Clojure希望你能够主要编写没有副作用的函数。

这是一个JavaScript互操作可能会很痛苦的示例,因为esrecurse.visit实际上没有返回值,因此调用map会返回一系列nil值。我很想把匿名函数拉出来并重新定义它以便总是返回它传递的AST。

(defn visit [ast]
  (.visit esrecurse ast #js {:Literal print})
  ast)

(defn mutate?
  "applies a mutation to the ASTs,
  returns the mutated, or non mutated, ASTs"
  [asts]
  (map visit asts))

(doall
  (mutate? (reader/to-ast (reader/read "./test/example-project/lib"))))

就像抬头一样,mutate?将是命名一个返回布尔值的函数的约定。也许你的意思是mutate!,这可能是一个可能会产生副作用的函数的惯例?