2010-07-26 237 views

回答

109

在Clojure 1.2中,您可以像修改地圖一樣解構rest參數。這意味着您可以執行命名的非定位關鍵字參數。這裏有一個例子:

user> (defn blah [& {:keys [key1 key2 key3]}] (str key1 key2 key3)) 
#'user/blah 
user> (blah :key1 "Hai" :key2 " there" :key3 10) 
"Hai there10" 
user> (blah :key1 "Hai" :key2 " there") 
"Hai there" 
user> (defn blah [& {:keys [key1 key2 key3] :as everything}] everything) 
#'user/blah 
user> (blah :key1 "Hai" :key2 " there") 
{:key2 " there", :key1 "Hai"} 

任何您可以在解構一個Clojure的地圖可以在函數的參數列表來完成如上圖所示做。包括使用:或者爲這樣的參數定義默認值:

user> (defn blah [& {:keys [key1 key2 key3] :or {key3 10}}] (str key1 key2 key3)) 
#'user/blah 
user> (blah :key1 "Hai" :key2 " there") 
"Hai there10" 

但是這是在Clojure 1.2中。或者,在舊版本中,您可以這樣做來模擬相同的事情:

user> (defn blah [& rest] (let [{:keys [key1 key2 key3] :or {key3 10}} (apply hash-map rest)] (str key1 key2 key3))) 
#'user/blah 
user> (blah :key1 "Hai" :key2 " there") 
"Hai there10" 

並且工作原理大致相同。

而且你也可以有關鍵字參數之前來到位置參數:

user> (defn blah [x y & {:keys [key1 key2 key3] :or {key3 10}}] (str x y key1 key2 key3)) 
#'user/blah 
user> (blah "x" "Y" :key1 "Hai" :key2 " there") 
"xYHai there10" 

這些都不是可選的,並且必須提供。

實際上,您可以像處理任何Clojure集合一樣解構rest參數。

user> (defn blah [& [one two & more]] (str one two "and the rest: " more)) 
#'user/blah 
user> (blah 1 2 "ressssssst") 
"12and the rest: (\"ressssssst\")" 

即使在Clojure 1.1中你也可以做這種事情。但關鍵字參數的映射式解構僅在1.2版本中出現。

+5

感謝您的回答。 Lisp是GREAAAAT! :-) – 2010-07-26 19:23:41

+0

非常歡迎。是的。必然是。 =) – Rayne 2010-07-26 22:12:58

0

你的意思是命名參數?這些不是直接可用的,但如果你喜歡,你可以use this vectors approach,這可能會給你你想要的。

At RosettaCode有關如何使用解構來做到這一點的更深入的解釋。

+0

感謝您的回答! :-) – 2010-07-26 19:24:02

+3

@Abel你能分享你鏈接到的例子嗎? (他們有辦法改變或過時)。 – 2014-02-24 16:03:26

32

除了Raynes'出色答卷,也有a macro in clojure-contrib,讓生活更輕鬆:

 
user=> (use '[clojure.contrib.def :only [defnk]]) 
nil 
user=> (defnk foo [a b :c 8 :d 9] 
     [a b c d]) 
#'user/foo 
user=> (foo 1 2) 
[1 2 8 9] 
user=> (foo 1 2 3) 
java.lang.IllegalArgumentException: No value supplied for key: 3 (NO_SOURCE_FILE:0) 
user=> (foo 1 2 :c 3) 
[1 2 3 9] 
+6

我忘了提及!我都被Clojure展示了10萬種可以解構東西的方式。 :p – Rayne 2010-07-26 22:11:21

+0

clojure-contrib已棄用,我無法找到當前的替代方案。有任何想法嗎? – Lstor 2014-07-21 15:03:38

+1

@Lstor:在[prismatic/plumbing](https://github.com)查看[defnk](https://github.com/Prismatic/plumbing/blob/7ae0e85e4921325b3c41ef035c798c29563736dd/src/plumbing/core.cljx#L470) /棱鏡/管道) – Ian 2015-04-16 16:00:10