我想在地图中添加一个条目,但前提是地图不包含我想要添加的密钥.即我想要插入但不更新.为了他,我创造了2个功能:
(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))
Run Code Online (Sandbox Code Playgroud)
我的问题是,这两个功能已不存在吗?
另外,我对Clojure很新,有关实现的任何提示吗?
opt*_*evo 16
使用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}
Run Code Online (Sandbox Code Playgroud)
换一种说法:
(defn assoc-if-new [coll k v] (merge {k v} coll))
Run Code Online (Sandbox Code Playgroud)
(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))
Run Code Online (Sandbox Code Playgroud)
你犯了几个错误:
在
(defn assoc-if [pred coll k v]
(if pred (assoc coll k v) coll))
Run Code Online (Sandbox Code Playgroud)
...... pred没有被召集.既不是false也不是nil,它的功能价值将评估为真.因此该函数将始终返回(assoc coll k v).
在
(defn assoc-if-new [coll k v]
(assoc-if (not (contains? coll k)) coll k v))
Run Code Online (Sandbox Code Playgroud)
...第一个参数assoc-if应该是一个谓词 - 一个函数返回一个用于其真或假的值.(not (contains? coll k))将产生一个布尔值,在assoc-if尝试将其作为函数调用时导致错误.
assoc-if在内部调用调用.contains?的函数.标准功能就是complement这样做的.