clojure et ^:dynamique
J'ai essayé de comprendre la dynamique des variables et la fonction de liaison j'ai donc essayé ceci (clojure 1.3):
user=> (defn f []
(def ^:dynamic x 5)
(defn g [] (println x))
(defn h [] (binding [x 3] (g)))
(h))
#'user/f
user=> (f)
5
nil
Confus, j'ai essayé un peu plus simple de code:
user=> (def ^:dynamic y 5)
#'user/y
user=> (defn g [] (println y))
#'user/g
user=> (defn h [] (binding [y 3] (g)))
#'user/h
user=> (h)
3
nil
Quelle est la différence entre les deux morceaux de code? Pourquoi le deuxième exemple, le travail, mais la première ne l'est pas?
Astuce: je viens de réaliser que les œuvres suivantes (ne pas bien comprendre pourquoi):
user=> (def ^:dynamic y 5)
#'user/y
user=> (defn f [] (defn g [] (println y)) (defn h [] (binding [y 3] (g))) (h))
#'user/f
user=> (f)
3
nil
user=>
Vous devez vous connecter pour publier un commentaire.
- Je obtenir 3 à la suite (comme vous vous en doutiez) quand je lance votre premier exemple en Clojure 1.4.... avez-vous essayé avec une nouvelle REPL?
^:dynamic
est une instruction pour la Clojure compilateur qu'un symbole (comme défini avecdef
) est destiné à être dynamiquement rebond (avecbinding
).Exemple:
Noter que
binding
dynamique de portée dans le thread appelant - toutes les fonctions appelées dans la liaison va voir la valeur de modification debar
(20), mais les autres threads pourront toujours voir l'inchangée racine de la valeur de 10.Enfin, un couple de points de style que vous pourriez trouver utiles:
def
etdefn
à l'intérieur des fonctions en tant qu'ils affectent l'affichage de l'espace de noms. Dans les fonctions que vous devriez utiliser(let [foo bar] ...)
à la place.binding
normalement vous devriez envisager si vous pouvez obtenir le même résultat en utilisant des fonctions d'ordre supérieur à la place.binding
est utile dans certains contextes, mais il n'est en général pas une bonne façon de passer des paramètres autour de la fonction de composition est généralement mieux dans le long terme. La raison pour cela est quebinding
crée un contexte implicite qui est nécessaire pour l'exécution de votre fonction et il peut être difficile de test/debug.*barbells*
comme plus que juste de la convention.