2013-08-26 32 views
7

jestem nowicjuszem do Clojure i zastanawiałem się, czy istnieje sposób, aby zdefiniować funkcję, która może być wywołana tak:funkcji o zmiennej liczbie argumentów argumentów kluczowych

(strange-adder 1 2 3 :strange true) 

Oznacza to, że funkcja, która może odbierać zmienna liczba int i argument słowa kluczowego.

wiem, że mogę zdefiniować funkcję z argumentami słów kluczowych w ten sposób:

(defn strange-adder 
    [a b c & {:keys [strange]}] 
    (println strange) 
    (+ a b c)) 

Ale teraz moja funkcja może otrzymać tylko stałą liczbę int.

Czy istnieje sposób korzystania z obu stylów naraz?

Odpowiedz

8

Niestety, nie.

Operator destrukturyzacji używa wszystkich elementów po liście argumentów, więc nie ma możliwości obsługi dwóch różnych zestawów grup destrukturyzacji zmiennych arytmetycznych w jednej formie.

Jedną z opcji jest przełamanie funkcji na kilka podobieństw. Chociaż działa to tylko wtedy, gdy możesz to ustawić, więc tylko jeden z nich jest variadic (używa &). Bardziej uniwersalnym i mniej wygodnym rozwiązaniem jest traktowanie całej listy argumentów jako jednej formy variadycznej i ręczne wybieranie liczb od początku.

user> (defn strange-adder 
     [& args] 
     (let [nums (take-while number? args) 
       opts (apply hash-map (drop-while number? args)) 
       strange (:strange opts)] 
      (println strange) 
       (apply + nums))) 
#'user/strange-adder 
user> (strange-adder 1 2 3 4 :strange 4) 
4 
10 
1

Nie ma formalnego wsparcia, które znam, ale coś takiego powinno być wykonalne?

(defn strange-adder 
    [& args] 
    (if (#{:strange} (-> args butlast last)) 
    (do (println (last args)) 
     (apply + (drop-last 2 args))) 
    (apply + args))) 

nie wiem, czy to można uogólnić (sprawdź jak dla słów kluczowych, aby rozwinąć do dowolnej liczby ostatecznych argumentów?). Jedną opcją może być umieszczenie wszystkich opcji w mapie mieszającej jako ostatecznego argumentu i sprawdzenie, czy ostatni argument jest hashmap (ale to nie zadziałałoby dla niektórych funkcji, które oczekują arbitralnych argumentów, które mogłyby być hashmapami).

4

Przenieś część o zmiennej liczbie argumentów na ogonie listy argumentów i przejść do opcji mapy:

(defn strange-adder [{:keys [strange]} & nums] 
    (println strange) 
    (apply + nums)) 

(strange-adder {:strange true} 1 2 3 4 5) 
Powiązane problemy