clojure assoc-if和assoc-if-new

时间:2014-07-30 11:21:55

标签: clojure

我想在地图中添加条目,但前提是地图不包含我要添加的密钥。即我想做插入但不更新。因为他创造了两个功能:

(defn assoc-if [pred coll k v]
  (if pred (assoc coll k v) coll))

(defn assoc-if-new [coll k v]
  (assoc-if (not (contains? coll k)) coll k v))

我的问题是,这两个功能是否已经存在?

另外,我对Clojure很新,有关实现的任何提示吗?

2 个答案:

答案 0 :(得分:15)

使用merge,右手地图将始终覆盖左手地图,因此如果您反转参数并将其放入地图中,您将获得相同的行为:

(assoc-if-new {:a 1 :b 2} :b 3)
;=> {:a 1, :b 2}

(assoc-if-new {:a 1 :b 2} :c 3)
;=> {:c 3, :a 1, :b 2}

(merge {:b 3} {:a 1 :b 2})
;=> {:a 1, :b 2}

(merge {:c 3} {:a 1 :b 2})
;=> {:b 2, :a 1, :c 3}

换句话说:

(defn assoc-if-new [coll k v] (merge {k v} coll))

答案 1 :(得分:5)

(defn assoc-if [pred coll k v]
  (if (pred coll k) (assoc coll k v) coll))

(defn assoc-if-new [coll k v]
  (assoc-if (complement contains?) coll k v))

你犯了几个错误:

(defn assoc-if [pred coll k v]
  (if pred (assoc coll k v) coll))

... pred未被调用。既不是false也不是nil,它的函数值将评估为真。因此该函数将始终返回(assoc coll k v)

(defn assoc-if-new [coll k v]
  (assoc-if (not (contains? coll k)) coll k v))

... assoc-if的第一个参数应该是谓词 - 一个返回用于其真或假的值的函数。 (not (contains? coll k))将生成一个布尔值,当assoc-if尝试将其作为函数调用时会导致错误。

  • 不要明确提供参数:assoc-if调用调用 内部。
  • 如果要反转逻辑结果,则必须调整 function contains?函数,返回逻辑反转的结果。 标准函数complement执行此操作。