Wie Sie bereits bemerkt haben, bedeutet die Tatsache, dass von Veränderlichkeit in Clojure abgeraten wird, nicht, dass dies verboten ist und dass es keine Konstrukte gibt, die dies unterstützen. Sie haben also Recht, dass def
Sie mit einer Bindung eine Bindung in der Umgebung ähnlich wie die Zuweisung in anderen Sprachen ändern / mutieren können (siehe die Clojure-Dokumentation zu vars ). Durch Ändern von Bindungen in der globalen Umgebung ändern Sie auch Datenobjekte, die diese Bindungen verwenden. Zum Beispiel:
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
Beachten Sie, dass sich nach der Neudefinition der Bindung für x
auch die Funktion f
geändert hat, da ihr Körper diese Bindung verwendet.
Vergleichen Sie dies mit Sprachen, in denen die Neudefinition einer Variablen die alte Bindung nicht löscht, sondern nur schattiert , dh sie in dem Bereich unsichtbar macht, der nach der neuen Definition kommt. Sehen Sie, was passiert, wenn Sie denselben Code in die SML REPL schreiben:
- 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
Beachten Sie, dass x
die Funktion nach der zweiten Definition von f
immer noch die Bindung verwendet x = 1
, die zum Zeitpunkt der Definition im Gültigkeitsbereich war, dh die Bindung val x = 100
überschreibt die vorherige Bindung nicht val x = 1
.
Fazit: Mit Clojure können Sie die globale Umgebung mutieren und Bindungen darin neu definieren. Es wäre möglich, dies zu vermeiden, wie es andere Sprachen wie SML tun, aber das def
Konstrukt in Clojure soll auf eine globale Umgebung zugreifen und diese mutieren. In der Praxis ist dies sehr ähnlich zu dem, was die Zuweisung in imperativen Sprachen wie Java, C ++, Python tun kann.
Trotzdem bietet Clojure viele Konstrukte und Bibliotheken, die Mutationen vermeiden, und Sie können einen langen Weg zurücklegen, ohne sie überhaupt zu verwenden. Das Vermeiden von Mutationen ist bei weitem der bevorzugte Programmierstil in Clojure.