Clojure: как отправить оставшиеся аргументы и аргументы в список?

Есть ли какой-нибудь (разумный) способ записать этот макрос как функцию?

(defmacro assocTop
          [v & args]
          `(push (pop ~v)
                 (assoc (peek ~v) ~@args)))

Учитывая вектор карт и некоторые ассоциации, код макроса применяет ассоциации к верхней / просматриваемой карте.

Однако, пытаясь написать его как функцию, я не могу понять, как расширить ~@args законным способом. В обычных функциях есть способ превратить args, который, как мне кажется, имеет форму (:a 3 :bb 44 :cd 90,...) в :a 3 :bb 44 :cd 90,..., т.е. без парней?


person spacingissue    schedule 20.10.2012    source источник


Ответы (1)


Думаю, вам следует использовать apply, который применит assoc к (peek v) и расширит args.

(defn assocTop
  [v & args]
  (push (pop v)
        (apply assoc (peek v) args)))
(=
  (assocTop [{:a :b} {:c :d} {:e :f, :g :h}] :e :z)
  [{:a :b} {:c :d} {:g :h, :e :z}]) ; => true
person Jan    schedule 20.10.2012
comment
Почему reduce здесь не работает, а работает, скажем, с (defn push [v & args] (reduce conj v args))? - person spacingissue; 20.10.2012
comment
@spacingissue, я не понимаю, как вы хотите использовать reduce в этом случае. Вы можете уточнить? - person Jan; 20.10.2012
comment
Думаю, я думал, что повторное применение assoc к ответу будет таким же, как reduce. Есть ли различие в случае push (где вы многократно применяете конъюнктуру к ответу)? - person spacingissue; 20.10.2012