我正在寻找一种方法来应用一些默认值来映射。我知道以下工作:
(defn apply-defaults
[needing-defaults]
(merge {:key1 (fn1 10)
:key2 (fn2 76)}
needing-defaults))
上述问题是即使fn1
可能已经拥有这些密钥,也会评估fn2
和needing-defaults
的值 - 因此从不需要它们。
我尝试过合并但这似乎不起作用。我对此很陌生 - 有什么建议吗?
答案 0 :(得分:3)
我通常使用merge-with函数来应用默认值:
(merge-with #(or %1 %2) my-map default-map)
但在你的情况下它应该是这样的:
(reduce (fn [m [k v]]
(if (contains? m k) m (assoc m k (v))))
needing-defaults
defaults)
其中defaults
是函数映射:
{ :key1 #(fn1 10)
:key2 #(fn2 76)}
if
是一种特殊形式,因此它会更新评估其false
分支。
答案 1 :(得分:0)
如果我理解你的问题,那怎么样?
(defn apply-defaults [nd]
(into {:key1 (sf1 10) :key2 (sf2 76)} nd))
答案 2 :(得分:0)
由于您可以将nil
合并到地图中,因此您可以使用if-not
宏:
(merge {} nil {:a 1} nil) ;; {:a 1}
试试这个:
(defn apply-defaults [col]
(merge col
(if-not (contains? col :key1) {:key1 (some-function1 10)})
(if-not (contains? col :key2) {:key2 (some-function2 76)})))
some-function1
和some-function2
只会在col
尚未拥有密钥时执行。
答案 3 :(得分:0)
您可以使用宏来生成contains?
检查并使函数调用短路。
(defmacro merge-with-defaults [default-coll coll]
(let [ks (reduce (fn [a k] (conj a
`(not (contains? ~coll ~k))
`(assoc ~k ~(k default-coll))))
[] (keys default-coll))]
`(cond-> ~coll ~@ks)))
(defn apply-defaults [needing-defaults]
(merge-with-defaults {:key1 (fn1 10)
:key2 (fn2 76)}
needing-defaults))
请记住将函数调用保留在merge-with-defaults
的调用中以防止评估。