ดังที่คุณได้สังเกตเห็นแล้วความจริงที่ว่าความไม่แน่นอนนั้นเกิดขึ้นใน Clojure นั้นไม่ได้หมายความว่าเป็นสิ่งต้องห้ามและไม่มีสิ่งก่อสร้างที่รองรับ ดังนั้นคุณถูกต้องที่ใช้def
คุณสามารถเปลี่ยน / กลายพันธุ์ผูกพันในสภาพแวดล้อมในลักษณะที่คล้ายกับสิ่งที่ได้รับมอบหมายในภาษาอื่น ๆ (ดูเอกสาร Clojure บน vars ) ด้วยการเปลี่ยนการเชื่อมในสภาพแวดล้อมโกลบอลคุณจะเปลี่ยนวัตถุข้อมูลที่ใช้การเชื่อมเหล่านี้ ตัวอย่างเช่น:
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
โปรดสังเกตว่าหลังจากนิยามการโยงx
ใหม่อีกครั้งฟังก์ชั่นf
ก็เปลี่ยนไปเช่นกันเพราะร่างกายใช้การโยงนั้น
เปรียบเทียบสิ่งนี้กับภาษาที่การกำหนดตัวแปรใหม่ไม่ได้ลบการเชื่อมโยงเก่า แต่มีเพียงเงาเท่านั้นนั่นคือมันทำให้มองไม่เห็นในขอบเขตที่มาหลังจากนิยามใหม่ ดูว่าเกิดอะไรขึ้นถ้าคุณเขียนรหัสเดียวกันใน 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
แจ้งให้ทราบว่าหลังจากที่ความหมายที่สองของx
ฟังก์ชั่นf
ยังคงใช้ผูกพันx = 1
ที่อยู่ในขอบเขตเมื่อมันถูกกำหนดไว้คือผูกพันไม่ได้เขียนทับก่อนหน้านี้มีผลผูกพันval x = 100
val x = 1
Bottomline: Clojure อนุญาตให้เปลี่ยนแปลงสภาพแวดล้อมทั่วโลกและกำหนดการผูกใหม่ในนั้น มันเป็นไปได้ที่จะหลีกเลี่ยงสิ่งนี้เช่นเดียวกับภาษาอื่น ๆ เช่น SML แต่def
โครงสร้างใน Clojure นั้นมีจุดประสงค์เพื่อเข้าถึงและเปลี่ยนแปลงสภาพแวดล้อมของโลก ในทางปฏิบัติสิ่งนี้คล้ายกับสิ่งที่ได้รับมอบหมายสามารถทำได้ในภาษาที่จำเป็นเช่น Java, C ++, Python
ถึงกระนั้น Clojure ยังมีสิ่งก่อสร้างและห้องสมุดจำนวนมากที่หลีกเลี่ยงการกลายพันธุ์และคุณสามารถมาได้ไกลโดยไม่ต้องใช้เลย การหลีกเลี่ยงการกลายพันธุ์นั้นเป็นรูปแบบการเขียนโปรแกรมที่ต้องการใน Clojure