我想在地图中添加条目,但前提是地图不包含我要添加的密钥。即我想做插入但不更新。因为他创造了两个功能:
(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很新,有关实现的任何提示吗?
答案 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
调用调用
内部。contains?
到函数,返回逻辑反转的结果。
标准函数complement
执行此操作。