Let contre liaison dans Clojure
Question
Je comprends qu'ils sont différents car on travaille pour la mise en *compile-path*
et un ne fonctionne pas. Cependant, j'ai besoin d'aide avec pourquoi ils sont différents.
let
crée une nouvelle portée avec les fixations données, mais binding
...?
La solution
let
crée un alias immuable scope pour une lexicalement valeur. binding
crée une dynamique SCOPED obligatoire pour certaines Var
.
Liaison dynamique signifie que le code dans votre formulaire de binding
et tout code qui appelle ce code (même si pas dans le champ lexical local) verra la nouvelle liaison.
Vu:
user> (def ^:dynamic x 0)
#'user/x
binding
crée en fait une liaison dynamique pour une Var
mais let
ombres le var avec un alias local:
user> (binding [x 1] (var-get #'x))
1
user> (let [x 1] (var-get #'x))
0
binding
peut utiliser des noms qualifiés (car il fonctionne sur Var
s) et let
ne peut pas:
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
fixations introduites let
-ne sont pas mutable.
binding
-fil localement mutable
user> (binding [x 1] (set! x 2) x)
2
user> (let [x 1] (set! x 2) x)
; Evaluation aborted.
;; Invalid assignment target
lexicales par rapport à la liaison dynamique:
user> (defn foo [] (println x))
#'user/foo
user> (binding [x 1] (foo))
1
nil
user> (let [x 1] (foo))
0
nil
Autres conseils
Une autre différence syntaxique pour let vs lier:
Pour la liaison, toutes les valeurs initiales sont évaluées avant l'un d'eux sont liés aux vars. Ceci est différent de let, où vous pouvez utiliser la valeur d'une précédente « alias » dans une définition ultérieure.
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
lie une valeur à un nom dans l'environnement global par thread
Comme vous l'avez mentionné, let
crée un nouveau champ d'application pour ces liaisons.