Comme vous l'avez déjà remarqué, le fait que la mutabilité soit découragée dans Clojure ne signifie pas qu'elle est interdite et qu'il n'y a pas de constructions qui la supportent. Vous avez donc raison de dire que def
votre utilisation peut modifier / muter une liaison dans l'environnement d'une manière similaire à ce que fait l'affectation dans d'autres langues (voir la documentation de Clojure sur les vars ). En modifiant les liaisons dans l'environnement global, vous modifiez également les objets de données qui utilisent ces liaisons. Par exemple:
user=> (def x 1)
#'user/x
user=> (defn f [y] (+ x y))
#'user/f
user=> (f 1)
2
user=> (def x 100)
#'user/x
user=> (f 1)
101
Notez qu'après avoir redéfini la liaison pour x
, la fonction f
a également changé, car son corps utilise cette liaison.
Comparez cela avec les langages dans lesquels la redéfinition d'une variable ne supprime pas l'ancienne liaison mais la masque uniquement , c'est-à-dire qu'elle la rend invisible dans la portée qui suit la nouvelle définition. Voyez ce qui se passe si vous écrivez le même code dans le SML REPL:
- val x = 1;
val x = 1 : int
- fun f y = x + y;
val f = fn : int -> int
- f 1;
val it = 2 : int
- val x = 100;
val x = 100 : int
- f 1;
val it = 2 : int
Notez qu'après la deuxième définition de x
, la fonction f
utilise toujours la liaison x = 1
qui était dans la portée lorsqu'elle a été définie, c'est-à-dire que la liaison val x = 100
n'écrase pas la liaison précédente val x = 1
.
Conclusion: Clojure permet de muter l'environnement global et de redéfinir les liaisons en son sein. Il serait possible d'éviter cela, comme le font d'autres langages comme SML, mais la def
construction de Clojure est destinée à accéder à un environnement global et à le muter. En pratique, cela est très similaire à ce que l'affectation peut faire dans des langages impératifs comme Java, C ++, Python.
Pourtant, Clojure fournit de nombreuses constructions et bibliothèques qui évitent la mutation, et vous pouvez faire du chemin sans l'utiliser du tout. Éviter la mutation est de loin le style de programmation préféré dans Clojure.