我在Chas Emerick等人的 Clojure Programming 中运行了一个例子:
(defn make-user
[& [uid]]
{:user-id (or uid (str (java.util.UUID/randomUUID)))})
输出:
=> (make-user" T-800")
{:user-id " T-800" }
现在我删除第2行中uid周围的方括号:
(defn make-user
[& uid]
{:user-id (or uid (str (java.util.UUID/randomUUID)))})
评估结果变为:
=> (make-user" T-800")
{:user-id (" T-800")}
如何理解这种差异?
答案 0 :(得分:3)
[&安培; uid]:
&
表示将所有参数放在一起作为名为uid
的列表。uid
这里是类型列表[&安培; [uid]]:
[uid]
,这是一个列表(不是因为[]
,而是在&
之后)。uid
uid
这里不是一个列表,只是一个元素。答案 1 :(得分:3)
在参数声明中,将参数放在&
旁边会导致它们被包装到列表中。
(defn return [x y & more]
[x y more])
(return 1 2 3 4 5 6)
;=> [1 2 (3 4 5 6)]
这种包装对于操作函数中未确定数量的args非常有用:
(defn plus [& more] (apply + more))
(plus 3 4)
;=> 7
(plus 3 4 5 6)
;=> 18
但是如果我们知道只有一个元素作为可选参数并希望直接访问它,我们可以使用first
来提取它:
(defn make-user-1 [& uid] {:user-id (first uid)})
(make-user-1 "T-800")
;=> {:user-id "T-800"}
或者,我们可以通过使用destructuring来解开参数元素!
(defn make-user-2 [& [uid]] {:user-id uid})
(make-user-2 "T-800")
;=> {:user-id "T-800"}
所以,这里有一些arg声明及其给定的输出:
(defn f [arg] arg) ;=> arg
(defn f [& arg] arg) ;=> (arg)
(defn f [& [arg]] arg) ;=> arg
你在arg声明中包装args的次数越多,在体内解包的次数就越多。