Як змусити функцію Clojure приймати змінну кількість параметрів?


80

Я вивчаю Clojure і намагаюся визначити функцію, яка приймає змінну кількість параметрів ( variadic функція) і підсумовує їх (так, як процедура +). Однак я не знаю, як реалізувати таку функцію

Все, що я можу зробити, це:

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

Звичайно, ця функція приймає лише два параметри та два параметри. Будь ласка, навчіть мене, як змусити його приймати (і обробляти) невизначену кількість параметрів.

Відповіді:


107

Загалом, некоммутативний випадок, який ви можете використовувати, застосовується :

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

Оскільки додавання є комутативним, щось подібне теж має працювати:

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

& призводить argsдо прив’язки до решти списку аргументів (у цьому випадку до цілого списку, оскільки зліва від нього немає нічого &).

Очевидно, що визначення такої суми не має сенсу, оскільки замість:

(sum a b c d e ...)

Ви можете просто написати:

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

3
Так, не робить сенсу, але це хороша ілюстрація вашої відповіді. Дякую.
rodrigoalvesvieira

@soulcheck: чи є спосіб передати a seqвашій функції суми. Наприклад: (сума '(1 2 3)) і результат 6?
avichalp

@avichalp, це була б інша функція. просто вилучіть &з будь-якої версії
soulcheck

1
@soulcheck: Ні. Я маю на увазі використання тієї ж функції підпису. Я новачок у Clojure, отже, я можу чітко висловити свою думку тут. Що я хотів би знати, це те, що в python я можу використовувати * args, і якщо функція визначена таким чином, що вона приймає * args (наприклад def fn(*args): pass), я можу зателефонувати їй, вказавши такий список, як fn (* list_of_args). Чи можу я зробити те саме в clojure?
avichalp

@avichalp заклик до def fn(*args): passне буде, fn([1,2,3])але fn(1,2,3)(очевидно, в залежності від того, що ти хочеш робити точно, але я намагаюся слідувати духу тут)
soulcheck

31

Єхоанафан згадує про перевантаження армії, але не подає прямого прикладу. Ось про що він говорить:

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

(special-sum) => 20

(special-sum 50) => 60

(special-sum 50 25) => 75


Також працює з лямбдами:(fn ([] (+ 10 10)) ([x] (+ 10 x)) ([x y] (+ x y)))
Ерік Каплун,

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

10

defn- це макрос, який робить визначення функцій дещо простішим. Clojure підтримує перевантаження arity в одному функціональному об'єкті, функції автоматичного посилання та функції змінної arity&

З http://clojure.org/functional_programming


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.