Pergunta

Quando utilizar ClojureScript tentei definir uma função que é um fechamento de mais de uma variável como este:

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

Que imprime a seguinte origem no Rhino REPL:

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

A função funciona como eu esperava, mas ao tentar chegar a variável com o nome x__43 Eu não posso fazê-lo.Para onde foi?

Foi útil?

Solução

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

atualmente é compilado para

var x__1311 = 42;

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

O número exato anexado ao x podem, é claro, variam de compilação para compilação e cljs.user poderia ser substituído por o apropriado nome de espaço para nome.

Não há nenhuma tentativa de esconder a variável gerado a partir relacionado código em JavaScript de encerramento, de modo que, em princípio, ela poderia ser modificada se um saiu de uma maneira para fazer isso.Colisões acidentais são extremamente improvável e simplesmente não vai acontecer com regular ClojureScript.

Para descobrir coisas como o acima, você pode chamar o compilador com {:optimizations :simple :pretty-print true} entre as opções, ou peça para que emitem um pouco de JavaScript no REPL (como o fornecido pelo script/repl no ClojureScript árvore de origem ou lein repl em um Leiningen projeto com ClojureScript declarado como uma dependência):

(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))))))

Outras dicas

a variável x é definido fora do foo função, no deixe de ligação.você não pode "pegar" porque você não está no escopo do let ligação.isso é mais ou menos o ponto de utilização de fechamentos.

conceitualmente, deixe enlaces são implementados como chamadas de função:

(let [x 2] ...)

é equivalente a

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

o que é provavelmente semelhantes let é implementado em ClojureScript - como uma macro de transformação para fn ou directamente para (function(x){...})(2).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top