如果这是一个真正基本的问题,我很抱歉,但我见过的一些代码让我很好奇。
apply
函数的惯用法是什么?
例如,我见过用以下形式编写的代码:
(distinct [1 2 3 4 5 6])
和
(apply distinct? [1 2 3 4 5 6])
这些返回相同的结果,甚至在文档中,它清楚地说:
;;请注意以下两种形式的等效性
用户=> (apply str [“str1”“str2”“str3”])“str1str2str3”
用户=> (str“str1”“str2”“str3”)“str1str2str3”
这个例子是否过于基本,无法传达apply
的用处?或者我错过了两者之间的根本区别?
什么时候一种形式被认为最好?
答案 0 :(得分:5)
user=> (apply str ["str1" "str2" "str3"]) "str1str2str3"
user=> (str "str1" "str2" "str3") "str1str2str3"
在此示例中,使用apply
的优点是它可以获取字符串列表。 str
本身不能。
我不是专家,但我的直觉说除非必要,否则不应使用apply
。因此,如果您有一组要传递给可变参数函数的值,apply
很有用 - 否则,只需使用普通函数,例如: str
。
答案 1 :(得分:4)
这些都是正确的,但原因各不相同:
(distinct? [1 2 3 4 5 6])
;=> true
只有一个参数,1..6的向量, 它与任何其他论点截然不同,因为那里 没有其他参数
(apply distinct? [1 2 3 4 5 6])
;=> true
有6个参数,所有参数都是不同的。
观察:
(distinct? [1 1 1])
;=> true
只有一个参数,即三个1
s
(apply distinct? [1 1 1])
;=> false
有三个参数,其中三个都是1
。
注意区别:
(str [1 2 3])
;=> "[1 2 3]" -- single argument of a vector stringified
(apply str [1 2 3])
;=> "123" -- three arguments each stringified and concatenated
对转化(apply f [a b c]) => (f a b c)
应用效果,通常不与(f [a b c])
相同。
答案 2 :(得分:2)
如果要将集合视为函数的参数,请使用apply
。在distinct
的情况下,它需要一个集合作为它的参数,因此没有必要使用apply
。
(distinct [1 2 3 4 1 1])
;returns: (1 2 3 4)
如果 distinct?
的参数不同,则返回true:
(distinct? [1 2 3 4 1 1])
;returns true because there's only one argument
apply
使用集合中的项作为参数:
(apply distinct? [1 2 3 4 1 1])
;returns false because of the duplicated 1's
答案 3 :(得分:1)
通常,我在调用函数时使用apply
将向量转换为参数。这与JavaScript中的apply
函数非常相似,如here
str
之类的函数是可变参数,并且期望与输入相同的类型,在本例中,是实现toString
的任何内容。使用(str a b c)
是惯用的,(apply str [a b c])
不是。
当您有一个异构向量时,可以使用函数apply
,该向量的项目要用作函数的参数。您可能会发现需要创建向量列表,其中向量中的项对应于函数的参数,然后必须使用apply
。
我认为apply
为:将矢量爆炸成参数。
示例:
(def authtypes [:basic :basic :oauth])
(def usernames ["charlie" "snoopy" "lisa"])
(def passwords ["brown" "dog" "maggie"])
(let [credentials (map vector authtypes usernames passwords)]
(doseq [c credentials]
(apply login-user c)))