2010-07-26 199 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