Daha önce fark ettiğiniz gibi, Clojure'da değişebilirliğin cesaret kırılması, yasak olduğu ve onu destekleyen hiçbir yapı olmadığı anlamına gelmez. Bu nedenle def
, kullanımınızı ortamdaki bir bağlayıcıyı diğer dillerde yapılan ödeve benzer şekilde değiştirebilir / değiştirebilirsiniz ( vars hakkındaki Clojure belgelerine bakın ). Global ortamda bağlantıları değiştirerek, bu bağlantıları kullanan veri nesnelerini de değiştirirsiniz. Örneğin:
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
Bağlamayı yeniden tanımladıktan sonra x
, işlevinin f
de değiştiğine dikkat edin , çünkü vücudu bu bağlamayı kullanır.
Bunu, bir değişkeni yeniden tanımlamanın eski bağlamayı silmediği, yalnızca gölgelediği , yani yeni tanımdan sonra gelen kapsamda görünmez kıldığı dillerle karşılaştırın . SML REPL'e aynı kodu yazarsanız ne olacağını görün:
- 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
İkinci tanımından sonra, x
işlevin tanımlandığı sırada f
hala x = 1
kapsamda olan bağlamayı kullandığına , yani bağlamanın val x = 100
önceki bağlamanın üzerine yazmadığına dikkat edin val x = 1
.
Alt satır: Clojure, küresel ortamı değiştirmeye ve içindeki bağları yeniden tanımlamaya izin verir. SML gibi diğer diller gibi bundan kaçınmak mümkün olabilir, ancak def
Clojure'daki yapı küresel bir ortama erişmek ve değiştirmek anlamına gelir. Uygulamada bu, Java, C ++, Python gibi zorunlu dillerde atamanın yapabileceklerine çok benzer.
Yine de, Clojure mutasyondan kaçınan birçok yapı ve kütüphane sağlar ve onu kullanmadan uzun bir yol kat edebilirsiniz. Mutasyondan kaçınmak Clojure'da tercih edilen programlama stilidir.