2013-08-26 2 views
7

Я новичок в Clojure и мне было интересно, если есть способ, чтобы определить функцию, которую можно назвать так:функция VARIADIC с аргументами ключевого слова

(strange-adder 1 2 3 :strange true) 

То есть функция, которая может принимать переменное число ints и аргумент ключевого слова.

Я знаю, что я могу определить функцию с аргументами ключевого слова таким образом:

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

Но теперь моя функция может принимать только фиксированное количество Интс.

Есть ли способ использовать оба стиля одновременно?

ответ

8

К сожалению, нет.

Оператор деструкции & использует все, что находится после него в списке аргументов, поэтому он не имеет возможности обрабатывать два разных набора групп деструктурирования переменных arity в одной форме.

Один из вариантов - разбить функцию на несколько артов. Хотя это работает, только если вы можете организовать его, так что только один из них является вариативным (использует &). Более универсальным и менее удобным решением является рассмотрение всего списка аргументов как одной вариационной формы и выбор номеров с самого начала вручную.

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

Там нет формальной поддержки, что я не знаю, но что-то, как это должно быть выполнимо:

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

Я не знаю, если это может быть обобщена (проверка ключевых слов, как расширить к произвольному числу конечных аргументов?). Один из вариантов может помещать все параметры в hashmap в качестве последнего аргумента и проверять, является ли последний аргумент хэш (но это не сработает для некоторых функций, которые ожидают произвольные аргументы, которые могут быть hashmaps).

4

Перемещение VARIADIC части к хвосту списка аргументов и передать параметры как карта:

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

(strange-adder {:strange true} 1 2 3 4 5) 
Смежные вопросы