如何使Clojure函数采用可变数量的参数?


80

我正在学习Clojure,并且正在尝试定义一个函数,该函数采用可变数量的参数(可变参数函数)并将它们相加(是的,就像+过程一样)。但是,我不知道如何实现这种功能

我所能做的是:

(defn sum [n1, n2] (+ n1 n2))

当然,该功能仅采用两个参数和两个参数。请教我如何使其接受(和处理)数量不确定的参数。

Answers:


107

通常,您可以使用apply

(defn sum [& args] (apply + args))

由于加法是可交换的,因此类似的事情也应该起作用:

(defn sum [& args] (reduce + args))

& 导致args绑定到参数列表的其余部分(在本例中为整个列表,因为的左边没有任何内容&)。

显然,像这样定义总和是没有意义的,因为它不是:

(sum a b c d e ...)

你可以这样写:

(+ a b c d e ....)

3
是的,没有任何意义,但这是您答案的一个很好的例证。谢谢。
rodrigoalvesvieira 2012年

@soulcheck:有一种方法可以将a传递seq给您的sum函数。例如:(sum'(1 2 3)),结果为6?
avichalp

@avichalp将是另一个功能。只需&从任何一个版本中删除
soulcheck

1
@soulcheck:不,我的意思是使用相同的函数签名。我是Clojure的新手,因此我可以在这里明确说明我的观点。我想知道的是在python中我可以使用* args,并且如果定义了一个函数def fn(*args): pass以使其带有* args(例如),我可以通过给出类似fn(* list_of_args)的列表来调用它。我可以在Clojure中做同样的事情吗?
avichalp

@avichalp调用def fn(*args): pass不会fn([1,2,3]),但fn(1,2,3)(显然这取决于你想要做什么,但我想在这里跟随灵)
soulcheck

31

Yehoanathan提到了arity重载,但没有提供直接的示例。他在说什么:

(defn special-sum
  ([] (+ 10 10))
  ([x] (+ 10 x))
  ([x y] (+ x y)))

(special-sum) => 20

(special-sum 50) => 60

(special-sum 50 25) => 75


也可用于lambda:(fn ([] (+ 10 10)) ([x] (+ 10 x)) ([x y] (+ x y)))
Erik Kaplun '18年

17
 (defn my-sum
  ([]  0)                         ; no parameter
  ([x] x)                         ; one parameter
  ([x y] (+ x y))                 ; two parameters
  ([x y & more]                   ; more than two parameters


    (reduce + (my-sum x y) more))
  )


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.