¿Cómo hacer que una función de Clojure tome un número variable de parámetros?


80

Estoy aprendiendo Clojure y estoy tratando de definir una función que tome un número variable de parámetros (una función variada ) y los resuma (sí, como el procedimiento +). Sin embargo, no sé cómo implementar dicha función.

Todo lo que puedo hacer es:

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

Por supuesto, esta función toma dos parámetros y solo dos parámetros. Enséñame cómo hacer que acepte (y procese) un número indefinido de parámetros.

Respuestas:


107

En general, el caso no conmutativo que puede utilizar aplica :

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

Dado que la suma es conmutativa, algo como esto también debería funcionar:

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

& hace argsque se vincule al resto de la lista de argumentos (en este caso, la lista completa, ya que no hay nada a la izquierda de &).

Obviamente, definir una suma así no tiene sentido, ya que en lugar de:

(sum a b c d e ...)

puedes simplemente escribir:

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

3
Sí, no tiene sentido, pero es una buena ilustración para tu respuesta. Gracias.
rodrigoalvesvieira

@soulcheck: ¿hay alguna manera de pasar un seqa su función de suma? Por ejemplo: (sum '(1 2 3)) y el resultado es 6?
avichalp

@avichalp esa sería otra función. basta con retirar &de cualquiera de las versiones
soulcheck

1
@soulcheck: No. Me refiero a usar la misma firma de función. Soy un novato en clojure, por lo tanto, puedo expresar mi punto claramente aquí. Lo que me gustaría saber es que en Python puedo usar * args y si una función está definida de manera que tome * args (por ejemplo def fn(*args): pass), puedo llamarla dando una lista como fn (* list_of_args). ¿Puedo hacer lo mismo en clojure?
avichalp

@avichalp, la llamada a def fn(*args): passno sería, fn([1,2,3])pero fn(1,2,3)(obviamente, dependiendo de lo que quieras hacer exactamente, pero estoy tratando de seguir el espíritu aquí)
soulcheck

31

Yehoanathan menciona la sobrecarga de aridad pero no proporciona un ejemplo directo. Esto es de lo que está hablando:

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

(special-sum) => 20

(special-sum 50) => 60

(special-sum 50 25) => 75


También funciona con lambdas:(fn ([] (+ 10 10)) ([x] (+ 10 x)) ([x y] (+ x y)))
Erik Kaplun

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))
  )


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.