Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clojure assoc-if and assoc-if-new

Tags:

clojure

I want to add an entry to a map but only if the map does not contain the key that I want to add. I.e. I want to do insert but not update. For his I created 2 functions:

(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))

My question is, do these two functions not exist already?

Also, I'm pretty new to Clojure, any tips on the implementation?

like image 910
shmish111 Avatar asked Jul 30 '14 11:07

shmish111


2 Answers

With merge the right hand map will always overwrite the left hand map so if you reverse your arguments and put them in a map you get the same behaviour:

(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}

In other words:

(defn assoc-if-new [coll k v] (merge {k v} coll))
like image 132
optevo Avatar answered Oct 20 '22 21:10

optevo


(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))

You made a couple of errors:

In

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

... pred is not called. Being neither false nor nil, its function value will evaluate true. So the function will always return (assoc coll k v).

In

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

... the first argument to assoc-if should be a predicate - a function returning a value used for its truth or falsehood. (not (contains? coll k)) will produce a boolean value, causing an error when assoc-if tries to call it as a function.

  • Don't supply the arguments explicitly: assoc-if concocts the call internally.
  • If you want to invert the logical result, you have to adapt the function contains? to a function that returns the logically inverted result. The standard function complement does this.
like image 6
Thumbnail Avatar answered Oct 20 '22 23:10

Thumbnail