Clojure 學習/評估
外觀
字串、數字、字元、nil、true、false 和關鍵字自身評估。當評估器遇到這些內容時,它只需將它們原樣返回。
當評估器遇到向量或雜湊對映時,它會遍歷並評估內容,然後返回向量或雜湊對映。實際上,如果向量或雜湊對映只包含字串、數字、字元、nil、true、false、關鍵字以及其他向量或雜湊對映,則向量/雜湊對映將原樣返回。
["eat my shorts" \space 35.6 true {:fred 22 :alison 8}] ; will simply be returned by the evaluator
但是,列表和符號的評估方式不同。
評估器根據符號的型別解析符號。
一個名稱空間限定符號解析為對映到指定名稱空間中符號的 Var 的根繫結。
hedgehog/rabbit ; a symbol resolving to the root binding of the Var mapped to rabbit in the namespace hedgehog
雖然類可以在名稱空間中引用,但名稱空間限定符號永遠只解析為 Var。如果符號沒有命名任何 Var,則會丟擲異常。
一個包限定符號(包含 . 的符號)解析為一個類。
java.util.Arrays ; a symbol resolving to the Class Arrays in the package java.util
如果找不到這樣的類,則會丟擲異常。
非限定符號的解析更加複雜。
- 如果符號是列表中的第一個專案,並且與十幾個特殊形式名稱之一匹配,則該列表是特殊形式,並且以特殊方式評估(稍後討論)。
- 如果不是,則該符號可能對映到當前名稱空間中引用的類。
- 如果不是,則該符號可能對映到區域性變數(區域性變數由特殊形式建立,我們將在稍後看到)。
- 如果不是,則該符號可能對映到在當前名稱空間中內聯或引用的 Var 的繫結。(這可能是根繫結或執行緒區域性繫結,如前所述。)
- 如果不是,則該符號解析為空,並丟擲異常。
[為什麼類查詢必須在區域性變數之前完成?區域性變數名稱不應該優先於類名?]
(另一種理解符號解析的方法是它們解析為 Vars,而 Vars 又依次評估為它們繫結的值。這大體上是正確的,但請注意,名稱空間限定符號始終解析為根繫結值,無論執行緒上下文如何。)
空列表簡單地評估為自身。
() ; the evaluator returns this as is
傳遞給評估器的非空列表應以符號或另一個列表開頭。如果列表以符號開頭
- 如上所述,以不限定符號開頭的列表,該符號匹配特殊形式名稱,將以特殊方式評估。
- 否則,該符號可能解析為一個包含宏的 Var(一種特殊型別的函式,我們將在稍後看到),在這種情況下,列表的其餘元素將保持未評估,並傳遞給宏的呼叫。宏返回的值將替換宏呼叫,然後進行評估。
- 否則,該符號應解析為一個包含函式的 Var,在這種情況下,列表的其餘元素將進行評估(從左到右),然後傳遞給函式的呼叫。列表的評估返回函式返回的值。
- 否則,將丟擲異常。
例如
(def x 3) ; def is a special form, so this list is evaluated specially (rooster ox (lion 3))
假設rooster解析為一個宏,則該宏將使用ox符號和(lion 3)列表的引數進行呼叫。但是,如果rooster解析為一個普通函式,則該函式將使用從ox解析的值和(lion 3)評估返回的值作為引數進行呼叫。
不太常見的是,列表可能以另一個列表開頭。在這種情況下,將評估初始列表,並期望它返回一個要呼叫的宏或函式(或返回一個繫結到宏或函式的 Var)。
((hamster) "moo") ; if (hamster) returns a function, that function is called with the argument "moo"