跳轉到內容

Clojure 學習/評估

來自華夏公益教科書

字串、數字、字元、niltruefalse 和關鍵字自身評估。當評估器遇到這些內容時,它只需將它們原樣返回。

當評估器遇到向量或雜湊對映時,它會遍歷並評估內容,然後返回向量或雜湊對映。實際上,如果向量或雜湊對映只包含字串、數字、字元、niltruefalse、關鍵字以及其他向量或雜湊對映,則向量/雜湊對映將原樣返回。

["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

如果找不到這樣的類,則會丟擲異常。

非限定符號的解析更加複雜。

  1. 如果符號是列表中的第一個專案,並且與十幾個特殊形式名稱之一匹配,則該列表是特殊形式,並且以特殊方式評估(稍後討論)。
  2. 如果不是,則該符號可能對映到當前名稱空間中引用的類。
  3. 如果不是,則該符號可能對映到區域性變數(區域性變數由特殊形式建立,我們將在稍後看到)。
  4. 如果不是,則該符號可能對映到在當前名稱空間中內聯或引用的 Var 的繫結。(這可能是根繫結或執行緒區域性繫結,如前所述。)
  5. 如果不是,則該符號解析為空,並丟擲異常。

[為什麼類查詢必須在區域性變數之前完成?區域性變數名稱不應該優先於類名?]

(另一種理解符號解析的方法是它們解析為 Vars,而 Vars 又依次評估為它們繫結的值。這大體上是正確的,但請注意,名稱空間限定符號始終解析為根繫結值,無論執行緒上下文如何。)

列表評估

[編輯 | 編輯原始碼]

空列表簡單地評估為自身。

()    ; the evaluator returns this as is

傳遞給評估器的非空列表應以符號或另一個列表開頭。如果列表以符號開頭

  1. 如上所述,以不限定符號開頭的列表,該符號匹配特殊形式名稱,將以特殊方式評估。
  2. 否則,該符號可能解析為一個包含的 Var(一種特殊型別的函式,我們將在稍後看到),在這種情況下,列表的其餘元素將保持未評估,並傳遞給宏的呼叫。宏返回的值將替換宏呼叫,然後進行評估。
  3. 否則,該符號應解析為一個包含函式的 Var,在這種情況下,列表的其餘元素將進行評估(從左到右),然後傳遞給函式的呼叫。列表的評估返回函式返回的值。
  4. 否則,將丟擲異常。

例如

(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"
華夏公益教科書