2010-04-05 37 views
5

如果我做到以下幾點:(部分申請STR),並應用-STR在Clojure的 - >

user=> (-> ["1" "2"] (partial apply str)) 
#<core$partial__5034$fn__5040 [email protected]> 

...我收到了部分功能了。但是,如果我將它綁定到一個變量:

user=> (def apply-str (partial apply str)) 
#'user/apply-str 
user=> (-> ["1" "2" "3"] apply-str)  
"123" 

...代碼按照我的意圖工作。我會假設他們是同一件事,但顯然情況並非如此。有人可以解釋爲什麼這對我來說?

回答

6

- >是一個宏,所以它不必遵循您期望的應用程序規則。宏在表單評估之前轉換源。嘗試macroexpanding形式:

user> (macroexpand '(-> ["1" "2"] (partial apply str))) 
(partial ["1" "2"] apply str) 

什麼是你想在這裏通過實現「 - >」宏?

編輯:需要注意的是:

user> ((partial apply str) ["1" "2"]) 
"12" 
+0

我想寫的代碼比這更復雜一些。這只是一個簡單的例子。我只想更好地理解' - >'宏如何工作。 :-) – 2010-04-05 11:39:38

+0

啊,陷阱。無論如何,你看到這裏發生了什麼? – 2010-04-05 14:02:59

+0

是的,我願意。感謝您的回答! – 2010-04-09 11:35:53

5

你不必這樣做的。

(->> ["1" "2" "3"] (apply str)) 

爲什麼不這樣做呢?

4

第一個表達式,,擴展爲:

(partial ["1" "2"] apply str)這基本上意味着:

創建從["1" "2"]的函數(這也是一個功能,因爲載體是索引鍵的功能!)與瓦爾已經提供了applystr作爲前兩個參數。這個函數被打印成奇怪的#<core$partial...>字符串。 只有當這個函數被調用時,你會得到一個IllegalArgumentException,因爲向量只有一個整數參數,而不是兩個Var參數。

+0

請注意,Clojure是動態的向量是函數的事實並不重要,這個bug。 (部分「hello」「world」)也會返回一個函數 - 一個總是拋出的函數。 – cgrand 2010-04-12 09:31:52

0

->宏在第二個版本中增加了圍繞apply-str的變形,這就是爲什麼宏擴展到最終調用函數的代碼。看看爲->的源代碼,你可以看到:

(defmacro -> 
    "Threads the expr through the forms. Inserts x as the 
    second item in the first form, making a list of it if it is not a 
    list already. If there are more forms, inserts the first form as the 
    second item in second form, etc." 
    ([x] x) 
    ([x form] (if (seq? form) 
       (with-meta `(~(first form) ~x [email protected](next form)) (meta form)) 
       (list form x))) 
    ([x form & more] `(-> (-> ~x ~form) [email protected]))) 

相關的部分是,當它在處理兩個參數,xform。如果form是seq,則將x作爲該列表中的第二個參數插入。否則,宏將它自己放入一個列表中,並將它放入列表formx。這樣您就可以使用裸符號作爲包含一個符號的列表的簡寫。

user> (macroexpand '(-> 123 (foo))) 
(foo 123) 
user> (macroexpand '(-> 123 foo)) 
(foo 123) 
1

宏觀- 通過形式第二個參數>線程的EXPR。在你的情況最終擴展到:(partial ["1" "2"] apply str),創建一個基於矢量的組合功能。

但要調用基於應用和STR上螺紋EXPR一個parital功能,因此需要:

(-> ["1" "2"] ((partial apply str))) 

好:這個代碼我相當混亂,而不是慣用的Clojure。