2016-09-16 76 views
2

我對差異的行爲感到困惑以下表達式:Clojure的元數據

(pr (meta ^{:a 0} (list 1 2))) ;; prints nil returns nil 

(pr (meta ^{:a 0} '(1 2)));; prints {:line 110, :column 20} returns nil 

(pr (meta ^{:a 0} (range 1 3))) ;; prints nil returns nil 

(pr (meta ^{:a 0} [1 2])) ;; prints {:a 0} returns nil 

這是使用Clojure的1.8.0。我希望能解釋爲什麼結果會有所不同。

回答

5

閱讀器元數據附加到閱讀器返回的表單。在每種情況下,調用meta的任何形式在運行時評估。一方與另一方之間沒有必要的聯繫。

如果您需要在運行時將元數據附加到值,則可以使用with-meta來完成此操作。

讓我們來看看在每個問題中列出的情況下會發生什麼:

  1. (pr (meta ^{:a 0} (list 1 2)))

    讀者的元數據附加到列表結構(list 1 2),但meta並不適用於本列表結構,而是在運行時評估它的值,這將是一個沒有附加元數據的兩個項目的新分配列表。

  2. (pr (meta ^{:a 0} '(1 2)))

    閱讀器的元數據附加到列表結構(quote (1 2))(單引號字符爲(quote …)讀者簡寫),但meta不被施加到這個清單的結構,但該值它在運行時評估爲,這是讀者在讀這個表達式時創建的(1 2)列表結構。這包含{:line … :column …}元數據,因爲Clojure閱讀器將該元數據附加到某些類型的表單以用於錯誤消息等。

  3. (pr (meta ^{:a 0} (range 1 3)))

    同上第一種情況。

  4. (pr (meta ^{:a 0} [1 2]))

    這是非常相似的'(1 2)情況與關鍵的差別,如果他們不被作爲功能/宏調用處理,而非空列表需要被引用,載體不和因此閱讀器元數據實際上附加到感興趣的文字 - 矢量 - 本身。

    這是可行的一個列表,以及:

    (pr (meta ' ^{:a 0} (1 2))) 
         ^note the quote comes before the metadata 
    ;; prints {:line 1, :column 14, :a 0} 
    

    NB。顯式閱讀器元數據映射被合併到{:line … :column …}映射中,讀者自己添加。