2013-04-06 31 views
0

這是爲什麼有效:Clojure的公案第8,#5

(= '(:anything :goes :here) (filter (fn [x] true) '(:anything :goes :here))) 

,但不爲呢?

(= (:anything :goes :here) (filter (fn [x] true) '(:anything :goes :here))) 

(= (:anything :goes :here) (filter (fn [x] true) (:anything :goes :here))) 

甚至

(= '(:anything :goes :here) (filter (fn [x] true) (:anything :goes :here))) 

有什麼特別的原因,第二對Arg的過濾器是帶引號的列表,而不是一個簡單的列表?

user=> (filter (fn [x] true) (:abc :def :ghi)) 
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:505) 

事實上,我仍然不確定列表是否也是一個函數調用。這與引用它似乎有關。除非列表爲空,否則需要引用所有「普通列表」嗎?

回答

2

評估列表時,第一個元素被假定爲一個函數(或宏或特殊形式)。

當列表的第一個元素是一個函數時,首先評估所有參數,然後將函數應用於結果值。

如果列表的第一個元素是宏或特殊形式,則根據宏/特殊形式可以評估或不評估每個參數。

Clojure將評估一個列表,其第一個元素是一個關鍵字,通過試圖找到該關鍵字作爲關鍵字函數的參數給定的關鍵字,然後返回相應的值,否則返回下一個參數(如果給定的話) 。因此(:anything :goes: :here)將返回here

'是一個讀取宏,將其參數放入quote特殊形式。 I.e.'anything =>(quote anything)

在你的情況:

=進行評價時,的(:anything :goes: here)和/或'(:anything goes here)值已進行評估。評估第一個將導致:here。 (在其他語言中會導致錯誤)。 '(:anything :goes :here),不過是(quote (:anything :goes :here))縮寫形式,並quote是一種特殊形式,它返回它的參數未計算,導致列表(:anything :goes: here),然後傳遞給=filter沒有進一步的評估。

然後發生了什麼事在每個案件是:

(= '(:anything :goes :here) (filter (fn [x] true) '(:anything :goes :here))) 

=是比較(:anything :goes :here)(:anything :goes :here),導致真正的

(= (:anything :goes :here) (filter (fn [x] true) '(:anything :goes :here))) 

:here相比(:anything :goes :here),造成假

(= (:anything :goes :here) (filter (fn [x] true) (:anything :goes :here))) 
(= '(:anything :goes :here) (filter (fn [x] true) (:anything :goes :here))) 

在這兩個中,filter應用於單個關鍵字:here,導致錯誤。

+0

我想這很值得說幾乎每個Lisp都是如此,而不僅僅是clojure – jozefg 2013-04-06 10:17:55

+0

你有點不對。 ':anything'是一個關鍵字,它被很好地定義爲一個函數。請參閱https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Keyword.java,'invoke(Object,Object)'方法。簡而言之,它詢問自己的第一個參數,如果第一個參數可以,並且它不能,它默認爲標準的'get'函數。在這兩種情況下,第二個參數都是默認值。所以下面的表達式:'(:abcd:defg:hijk)'將返回':hijk',作爲默認值。 – 2013-04-06 11:43:26

+0

@VladimirMatveev感謝您的更正。我現在已經更新了答案。 – 2013-04-06 12:56:33