## 變量
Clojure里面是不支持變量的。它跟變量有點像,但是在被賦值之前是不允許改的,包括:全局binding, 線程本地(thread local)binding, 以及函數內的本地binding, 以及一個表達式內部的binding。
`def` 這個special form 定義一個全局的 binding,并且你還可以給它一個”root value” ,這個root value在所有的線程里面都是可見的,除非你給它賦了一個線程本地的值. `def` 也可以用來改變一個已經存在的binding的root value —— 但是這是不被鼓勵的,因為這會犧牲不可變數據所帶來的好處。
函數的參數是只在這個函數內可見的本地binding。
`let` 這個special form 創建局限于一個 當前form的bindings. 它的第一個參數是一個vector, 里面包含名字-表達式的對子。表達式的值會被解析然后賦給左邊的名字。這些binding可以在這個vector后面的表達式里面使用。這些binding還可以被多次賦值以改變它們的值,let命令剩下的參數是一些利用這個binding來進行計算的一些表達式。注意:如果這些表達式里面有調用別的函數,那么這個函數是無法利用let創建的這個binding的。
宏 `binding` 跟 `let 類似` , 但是它創建的本地binding會暫時地覆蓋已經存在的全局binding. 這個binding可以在創建這個binding的form以及這個form里面調用的函數里面都能看到。但是一旦跳出了這個 `binding` 那么被覆蓋的全局binding的值會回復到之前的狀態。
從 Clojure 1.3開始, binding只能用在 動態變量(dynamic var)上面了. 下面的例子演示了怎么定一個dynamic var。另一個區別是 `let` 是串行的賦值的, 所以后面的binding可以用前面binding的值, 而 `binding` 是不行的.
要被用來定義成新的、本地線程的、用binding來定義的binding有它們自己的命名方式:她們以星號開始,以星號結束。在這篇文章里面你會看到: `*command-line-args*` , `*agent*` , `*err*` , `*flush-on-newline*` , `*in*` , `*load-tests*` , `*ns*` , `*out*` , `*print-length*` , `*print-level*` and `*stack-trace-depth*` .要使用這些binding的函數會被這些binding的值影響的。比如給*out*一個新的binding會改變println函數的輸出終端。
下面的例子介紹了 `def` , `let` 和 `binding` 的用法。
```
(def ^:dynamic v 1) ; v is a global binding
(defn f1 []
(println "f1: v =" v)) ; global binding
(defn f2 []
(println "f2: before let v =" v) ; global binding
(let [v 2] ; creates local binding v that shadows global one
(println "f2: in let, v =" v) ; local binding
(f1))
(println "f2: after let v =" v)) ; global binding
(defn f3 []
(println "f3: before binding v =" v) ; global binding
(binding [v 3] ; same global binding with new, temporary value
(println "f3: in binding, v =" v) ; global binding
(f1))
(println "f3: after binding v =" v)) ; global binding
(defn f4 []
(def v 4)) ; changes the value of the global binding
(f2)
(f3)
(f4)
(println "after calling f4, v =" v)
```
上面代碼的輸出是這樣的:
```
f2: before let v = 1
f2: in let, v = 2
f1: v = 1 (let DID NOT change value of global binding)
f2: after let v = 1
f3: before binding v = 1
f3: in binding, v = 3
f1: v = 3 (binding DID change value of global binding)
f3: after binding v = 1 (value of global binding reverted back)
after calling f4, v = 4
```