2013-03-24 53 views
4

考慮Clojure中#^ {...}和^ {...}元數據的區別?

(defn f ^{:foo "bar"} [x] (* x x)) 

(defn g #^{:foo "bar"} [x] (* x x)) 

編譯和運行。

我有兩個問題:第一,爲什麼(meta f)(meta g)只產生nil?我本來期待他們出示{:foo "bar"}; i.o.w.,我剛剛在元數據上吃了午飯,我是否定義了某種垃圾?

其次,元數據的兩種合成之間有什麼區別?它看起來像第二個是「tagged literal」,與edn, the extended data notation有關,但是我不能在沒有更多上下文或示例的情況下將它弄糊塗。

回答

8

The #^ metadata reader macro was replaced with^ in clojure 1.2。雖然兩者之間目前沒有區別,但舊形式已棄用,您應該專門使用^

元數據字面應該來之前它被附加到項目:

(defn ^{:foo "bar"} f [x] (* x x)) 

另一件事要記住的是,在上述定義的元數據沒有連接的功能,它附在涉及該功能的var上。

(meta (var f)) 

或者使用var讀者宏:你可以用得到的fvar元數據

(meta #'f) 
+0

感謝偉大的答案。我在看'(doc defn)',它說這個名字出現在元數據之前,除非我誤解了這個文檔:「clojure.core/defn ([name doc-string?attr-map?[params attr-map?([params *] prepost-map?body)+ attr-map?])「 – 2013-03-24 03:03:05

+1

'attr-map'是''attr-map''的一個特殊功能, defn'宏應該使元數據附加到定義的var更容易。當使用'attr-map'時,你不應該在地圖前加上'^'('(defn f {:foo「bar」} []:baz)')。我並沒有真正看到這個在任何地方使用,使用'^'閱讀器宏更常見。我猜'attr-map'在較舊版本的clojure中很有用,因爲在處理元數據時不太好用,但現在使用'^ {:foo「bar}'形式更具慣用性和更一般性(您可以放置​​它在任何可以保存元數據的對象之前)。 – mtyaka 2013-03-24 16:52:55