2013-05-22 3 views
3

У меня есть функция, которая принимает следующий видВыполнение функции, которая передает свои аргументы, как: ключи к другой функции

(defn foo [& {:keys [x y z]}] 
    ...) 

И я хочу, чтобы создать функцию, которая принимает только ключи у и г, но всегда дает x такое же значение. Я мог бы написать это

(defn bar [& {:keys [y z]}] 
    (foo :x "blah" :y y :z z)) 

Моя единственная проблема в том, что я должен повторить {: ключи ...} снова бит, и фактическая функция Foo имеет гораздо больше ключей, которые могут измениться в будущем. Есть ли способ заставить бар принять любые пары ключ-значение и просто передать их все в foo, удостоверившись, что x остается неизменным?

+1

Вам нужна ваша функция, чтобы быть вариационной? Или вы просто хотите передать карту? –

+0

Он должен быть переменным, я не хочу передавать карту. – Sotanaht

ответ

2

Это работает и отменяет любое :x значения, передаваемое bar:

(defn foo [& {:keys [ x y ]}] 
    [x y]) 

(defn bar [ & args ] 
    (apply foo (concat args [:x "blah"]))) 
+1

Было бы проблемой, если args of bar уже содержат: x значение. – mobyte

+0

Это именно то, о чем я просил. Спасибо :) – Sotanaht

+0

@mobyte Это действительно лучше, если он просто выдает ошибку, когда: x дается bar, потому что бару нужно только когда-либо понадобиться: x значение. – Sotanaht

1

При использовании амперсанда (&) вы объявляете VARIADIC функции. Возможно, вам не нужна ваша функция, чтобы быть вариационной. Вы можете просто сделать это:

(defn foo [{:keys [x y z]}] 
    [x y z]) 

(defn bar [{:keys [y z] :as args}] 
    (foo (assoc args :x "blah"))) 

И вы будете называть bar с картой, как это: (bar {:y 20 :z 10}). Если вам действительно нужно bar быть VARIADIC функции, вы можете просто сделать это (foo тем же сверху):

(defn bar [& {:keys [y z] :as args}] 
    (foo (assoc args :x "blah")) 

И вы будете продолжать называть bar так: (bar :y 10 :z 20). Вы также можете сделать foo variadic, но вам придется воссоздать список аргументов сами с чем-то вроде (flatten (map list (keys args) (vals args)))).

+0

Нет, я определенно нуждаюсь в этом, чтобы быть переменным. Фактическая функция foo просто помещает значения в запись, и некоторые из этих значений могут быть 'nil', когда функция запускается. – Sotanaht

2
(defn bar [& {:keys [y z] :as args}] 
    (apply foo (apply concat (assoc args :x "blah"))))