2

マップにいくつかのデフォルトを適用する方法を探しています。私は次の作品を知っています:

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

上記の問題は、これらのキーが既に存在する可能性がある場合でも、fn1およびの値fn2が評価されるため、それらが必要ないことです。needing-defaults

merge-with を試してみましたが、うまくいかないようです。私はこれにまったく慣れていません-何か提案はありますか?

4

4 に答える 4

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は特別な形式なので、 newer の方がそのfalseブランチを評価します。

詳細については、私の例を参照してください

于 2013-09-21T00:07:48.047 に答える
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

マクロを使用して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

あなたの質問を正しく理解できれば、これはどうですか?

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