Clojure bind-if and assoc-if-new

I want to add an entry to the card, but only if there is no key on the card that I want to add. That is, I want to insert, but not update. For him, I created 2 functions:

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

My question is, do these two functions no longer exist?

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

+6
source share
2 answers
 (defn assoc-if [pred coll kv] (if (pred coll k) (assoc coll kv) coll)) (defn assoc-if-new [coll kv] (assoc-if (complement contains?) coll kv)) 

You made a few mistakes:

IN

 (defn assoc-if [pred coll kv] (if pred (assoc coll kv) coll)) 

... pred not called. Not being false and nil , its function value will evaluate to true. Therefore, the function will always return (assoc coll kv) .

IN

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

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

  • Do not specify arguments explicitly: assoc-if calls inside.
  • If you want to invert the logical result, you need to adapt the function contains? to a function that returns a logically inverted result. The standard complement function does this.
+5
source

With merge right card will always overwrite the left hand card, so if you cancel your arguments and put them on the card, you will get the same behavior:

 (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 kv] (merge {kv} coll)) 
+14
source

Source: https://habr.com/ru/post/973094/


All Articles