2

我正在寻找一种将一些默认值应用于地图的方法。我知道以下作品:

(defn apply-defaults
  [needing-defaults]
  (merge {:key1 (fn1 10)
          :key2 (fn2 76)}
          needing-defaults))

上面的问题是,即使可能已经有这些键,也会评估fn1和的值 - 因此永远不需要它们。fn2needing-defaults

我已经尝试过合并,但这似乎不起作用。我对此很陌生-有什么建议吗?

4

4 回答 4

3

我通常使用合并功能应用默认值:

(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分支。

有关更多信息,请参阅我的示例

于 2013-09-21T00:07:48.047 回答
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以防止评估。

于 2013-09-20T22:45:57.690 回答
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没有密钥时执行。

于 2013-09-20T16:30:48.537 回答
0

如果我正确理解你的问题,这个怎么样?

(defn apply-defaults [nd]
    (into {:key1 (sf1 10) :key2 (sf2 76)} nd))
于 2013-09-20T16:19:05.570 回答