ClojureScript如何编译闭包?

问题描述:

当使用ClojureScript我试图定义一个函数,它是在这样的可变的封闭:ClojureScript如何编译闭包?

(let [x 42] 
    (defn foo [n] (+ x n))) 

,打印在犀牛REPL以下源:

function foo(n){ 
    return cljs.core._PLUS_.call(null,x__43,n); 
} 

功能工程,我期望但是当试图得到名为x__43的变量时,我无法得到它。它去了哪里?

+0

你是什么意思,你“不能得到它”?你的意思是评估Rhine repl上的'x__43'是不确定的吗? – liwp 2012-03-01 16:21:42

(let [x 42] 
    (defn foo [n] (+ x n))) 

目前编译为

var x__1311 = 42; 

cljs.user.foo = (function foo(n){ 
return (x__1311 + n); 
}); 

附接到x当然可以从汇编变化到汇编和cljs.user将由适当的名称空间名替换的确切数目。

没有试图在JavaScript关闭中隐藏不相关代码中的生成变量,所以原则上如果有人不这样做,它仍然可以被修改。偶然的碰撞是极不可能的,而且在普通的ClojureScript中不会发生。

要发现之类的东西上面,你可以调用编译器选项中{:optimizations :simple :pretty-print true}或要求它发出一些JavaScript在REPL(如通过在ClojureScript源代码树script/repllein repl与ClojureScript一个Leiningen项目提供宣布为依赖):

(require '[cljs.compiler :as comp]) 

(binding [comp/*cljs-ns* 'cljs.user] 
    (comp/emit 
    (comp/analyze {:ns {:name 'cljs.user} :context :statement :locals {}} 
       '(let [x 42] (defn foo [n] (+ x n)))))) 

x变量是在foo函数外定义的,在let绑定中。你不能“得到它”,因为你不在let绑定的范围内。这或多或少是使用闭包的关键。

概念,让绑定实现函数调用:

(let [x 2] ...) 

相当于

((fn [x] ...) 2) 

这是可能类似let在ClojureScript实现 - 无论是作为宏观转型fn或直接到(function(x){...})(2)