Pergunta

Eu entendo que eles são diferentes, desde um funciona para a criação *compile-path* e um não. No entanto, eu preciso de ajuda com isso eles são diferentes.

let cria um novo escopo com as ligações de dados, mas binding ...?

Foi útil?

Solução

let cria um alias de imutável escopo léxico para algum valor. binding cria um escopo dinamicamente vinculativo para alguns Var.

dinâmico significa que o código dentro de sua forma binding e qualquer código que que as chamadas de código (mesmo se não no escopo léxico local) verá a nova ligação.

obrigatório

Dada:

user> (def ^:dynamic x 0)
#'user/x

binding realmente cria uma ligação para um Var dinâmica, mas let apenas sombras do var com um alias local:

user> (binding [x 1] (var-get #'x))
1
user> (let [x 1] (var-get #'x))
0

binding pode usar nomes qualificados (uma vez que opera em Vars) e let não pode:

user> (binding [user/x 1] (var-get #'x))
1
user> (let [user/x 1] (var-get #'x))
; Evaluation aborted.
;; Can't let qualified name: user/x

ligações introduziu-let não são mutáveis. ligações introduziu-binding são thread-localmente mutável:

user> (binding [x 1] (set! x 2) x)
2
user> (let [x 1] (set! x 2) x)
; Evaluation aborted.
;; Invalid assignment target

ligação Lexical vs. dinâmico:

user> (defn foo [] (println x))
#'user/foo
user> (binding [x 1] (foo))
1
nil
user> (let [x 1] (foo))
0
nil

Veja também Vars , deixar .

Outras dicas

Uma diferença mais sintático para deixar vs ligação:

Para a ligação, todos os valores iniciais são avaliados antes de qualquer um deles está ligado ao Vars. Isso é diferente do let, onde você pode usar o valor de um "apelido" anterior em uma definição posterior.

user=>(let [x 1 y (+ x 1)] (println y))
2
nil

user=>(def y 0)
user=>(binding [x 1 y (+ x 1)] (println y))
1
nil

binding se liga um valor a um nome no ambiente global por thread

Como você mencionou, let cria um novo espaço para ditas ligações.

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