Reputation: 2177
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
Reputation: 86
Just use assoc-some
from the medley library. Battle-tested and widely used.
Upvotes: 1
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
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