Если посмотреть на то, что вы спрашиваете, я бы сказал, что один из способов сделать это - создать функцию, которая выглядит примерно так:
(pred-map
{:a [some-test-fn "one-value" "other-value"]
:b [some-test-fn 15 25]
:c [different-test :one :two]}
x
y)
, где x - аргумент для всех ссылок первого упоминанияfunction и y ко второму
способ достижения этого может быть следующим:
(defn get-value [p tv fv a]
(if (p a) tv fv))
(defn get-predicate-set [m]
(set (map first (vals m))))
(defn get-arg-map [m args]
(zipmap (get-predicate-set m) args))
(defn get-arg [p m args]
((get-arg-map m args) p))
(defn get-key-value-pair-creator [m args]
(fn [[k [p tv fv]]]
[k
(get-value
p
tv
fv
(get-arg p m args))]))
(defn pred-map [m & args]
(into {}
(map
(get-key-value-pair-creator m args)
m)))
Однако эти функции основаны на сопоставлении аргументов с функциями по равенству (что, кажется, идет со ссылками) поэтому он не будет понимать две равные анонимные функции как одну и ту же.
, если вы не возражаете повторять аргументы, вы создаете более простую функцию, похожую на эту:
(pred-map
{:a [(some-test-fn x) "one value" "other-value"]
:b [(some-test-fn x) 15 25]
:c [(different-test y) :one :two]})
, выполнивпростая функция:
(defn pred-map [m] (into {} (for [[k [p tv fv]] m] [k (if p tv fv)])))
или в стиле pointfree:
(def pred-map (comp (partial into {}) (partial map (fn [[k [p tv fv]]] [k (if p tv fv)]))))