Jak sprawić, by funkcja Clojure przyjmowała zmienną liczbę parametrów?


81

Uczę się Clojure i próbuję zdefiniować funkcję, która pobiera zmienną liczbę parametrów ( funkcja wariadyczna ) i podsumowuje je (tak, podobnie jak procedura +). Jednak nie wiem, jak zaimplementować taką funkcję

Wszystko, co mogę zrobić, to:

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

Oczywiście ta funkcja przyjmuje tylko dwa parametry i tylko dwa parametry. Naucz mnie, jak sprawić, by akceptował (i przetwarzał) niezdefiniowaną liczbę parametrów.

Odpowiedzi:


108

Ogólnie rzecz biorąc, nie przemiennej przypadku można użyć zastosowanie :

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

Ponieważ dodawanie jest przemienne, powinno też działać coś takiego:

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

& powoduje argszwiązanie się z pozostałą częścią listy argumentów (w tym przypadku całą listą, ponieważ nie ma nic po lewej stronie &).

Oczywiście definiowanie takiej sumy nie ma sensu, ponieważ zamiast:

(sum a b c d e ...)

możesz po prostu napisać:

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

3
Tak, nie ma sensu, ale to dobra ilustracja twojej odpowiedzi. Dzięki.
rodrigoalvesvieira

@soulcheck: czy istnieje sposób na przekazanie a seqdo funkcji sumującej . Na przykład: (sum '(1 2 3)) a wynik to 6?
avichalp

@avichalp to byłaby inna funkcja. po prostu usuń &z dowolnej wersji
soulcheck

1
@soulcheck: Nie. Mam na myśli używanie tego samego podpisu funkcji. Jestem nowicjuszem w ubraniu, więc jestem w stanie jasno przedstawić tutaj mój punkt widzenia. To, co chciałbym wiedzieć, jest w Pythonie. Mogę używać * args i jeśli funkcja jest zdefiniowana tak, że przyjmuje * args (np. def fn(*args): pass), Mogę ją wywołać, podając listę taką jak fn (* list_of_args). Czy mogę zrobić to samo w ubraniu?
avichalp

@avichalp wezwanie do def fn(*args): passnie byłoby, fn([1,2,3])ale fn(1,2,3)(oczywiście w zależności od tego, co dokładnie chcesz zrobić, ale staram się tu podążać za duchem)
soulcheck

31

Yehoanathan wspomina o przeciążaniu arity, ale nie podaje bezpośredniego przykładu. Oto, o czym on mówi:

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

(special-sum) => 20

(special-sum 50) => 60

(special-sum 50 25) => 75


Działa również z lambdami:(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))
  )


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.