Odinodin
Odinodin

Reputation: 2177

Assoc-if in Clojure

Is there an "assoc-if" function in the Clojure library? I.e if a value is truthy, update a map with a given key value. I've tried to find something to this effect, but came up lacking.

(defn assoc-if
  [m key value]
  (if value (assoc m key value) m))

Upvotes: 31

Views: 13494

Answers (3)

egli
egli

Reputation: 86

Just use assoc-some from the medley library. Battle-tested and widely used.

Upvotes: 1

Chouser
Chouser

Reputation: 5208

If the goal is to avoid repeating m, you can use conj:

(conj m (when value [key value]))

...or Clojure 1.5's new threading macros:

(-> m
  (cond-> value (assoc key value)))

If it's actually important to avoid repeating both the m and value, you'll have to write your own or reach outside clojure.core

Upvotes: 43

Leonid Beschastny
Leonid Beschastny

Reputation: 51500

There is no build-in assoc-if function in Clojure, but you're not the first one who needs it. Check this link with an implementation of assoc-if by ALEX MILLER:

(defn ?assoc
  "Same as assoc, but skip the assoc if v is nil"
  [m & kvs]
  (->> kvs
    (partition 2)
    (filter second)
    flatten
    (apply assoc m)))

But, since flatten is recursive, it's best to replace it with something which is not (thanks to kotarak for the hint). Another problem of this implementation is that (apply assoc m) will fail on empty list. So, it's best to replace it to:

(defn ?assoc
  "Same as assoc, but skip the assoc if v is nil"
  [m & kvs]
  (->> kvs
    (partition 2)
    (filter second)
    (map vec)
    (into m)))

Upvotes: 12

Related Questions