2011-12-09 42 views
3

像這樣:Clojure:當我重新輸入它的定義時,爲什麼函數的元數據會改變?

java -cp clojure.jar clojure.main 
Clojure 1.2.0 
user=> (defn f [x] x) 
#'user/f 
user=> (meta f) 
{:ns #<Namespace user>, :name f} 
user=> (defn f [x] x) 
#'user/f 
user=> (meta f) 
{:ns #<Namespace user>, :name f, :file "NO_SOURCE_PATH", :line 1, :arglists ([x])} 
user=> 

爲什麼不調用meta返回每次都相同的值?

更新:通過玩更多我能夠得到我的直接問題的答案。 defn宏擴展爲將(meta (var f)添加到f的元數據的表單。並且(meta (var f)包含第一次定義f時不在(meta f)中的額外信息。所以我的問題現在變成了,爲什麼defn這樣實現?

java -cp clojure.jar clojure.main 
Clojure 1.2.0 
user=> (defn f [x] x) 
#'user/f 
user=> (meta f) 
{:ns #<Namespace user>, :name f} 
user=> (meta (var f)) 
{:ns #<Namespace user>, :name f, :file "NO_SOURCE_PATH", :line 1, :arglists ([x])} 
user=> (macroexpand '(defn f [x] x)) 
(def f (.withMeta (clojure.core/fn f ([x] x)) (.meta (var f)))) ; (.meta x) seems to be the same as (meta x) 
user=> 

回答

0

Clojure的使用元數據來存儲,其中來自,文檔讀取的功能信息等重新定義該函數可以改變這種狀況。


http://clojure.org/metadata

一個重要的事情要了解有關的元數據是,它不被視爲一個對象的價值的一部分。因此,元數據不會影響平等(或散列碼)。僅在元數據上不同的兩個對象是相同的。

另一種方式來看待這是考慮相反:假設Clojure沒有重置元數據。

(defn fun [] 
    "docs for the original function" 
    ...) 

,然後重新定義它:

(defn fun [] 
    ;; no doc string, different body 
    ...) 

沒有元數據(doc fun)的重置將帶來的「原始功能的文檔」。

最後,vars的重新定義通常在開發過程中完成,通常不在程序的正常執行中。所以完全重新定義它是有道理的,而不是保留以前定義的東西。

+0

但我沒有重新定義函數,我只是第二次輸入相同的定義(並且讀取函數的位置也是相同的,即REPL)。根據固定表達式應該有一個常數值並應儘可能避免副作用的原則,看起來很奇怪的是,重複'defn'這樣的簡單操作可以爲元數據添加新的信息,這些信息可能已經第一次添加(我明白這不會影響表達的價值,但它仍然感覺不對)。 – OpenSauce

+0

即使函數相同,再次定義函數也是重新定義的。 Clojure不記得你的定義,只記得編譯好的代碼,它並不試圖比較舊的和新的。 – ivant

+0

好點,+1。但是,我發佈了來自Google小組的帖子,並接受了這個帖子,因爲它更接近我正在尋找的內容。 – OpenSauce

相關問題