A clj snippet #1

I haven't be blogging much recently and I still have the goal to write a total of 52 blogs posts this year. Even though the recent circumstances should give plenty of time to write, I have, so far, not found the willpower. The Why Not a Function series is setting a good example for short informative Clojure blog posts. So I took that as an inspiration and will try to start a little spinoff series called A clj snippet.

Today's snippet is stolen from the Ring clojure library.

(defn assoc-conj
  "Associate a key with a value in a map. If the key already exists in the map,
  a vector of values is associated with the key."
  [map key val]
  (assoc map key
    (if-let [cur (get map key)]
      (if (vector? cur)
        (conj cur val)
        [cur val])
      val))) 
0.1s
Clojure
user/assoc-conj

assoc-conj helps you deal with associative data where the keys are not unique. Where might this be useful? Consider urls which apparently can have multiple values per parameter name.

(require '[clojure.string :as str])
(let [url "http://server/action?id=a&id=b&token=xyz"
      [_ params] (str/split url #"\?")] ;; only for presentation purposes
   (reduce
      (fn [m param]
        (if-let [[k v] (str/split param #"=" 2)]
          (assoc-conj m (keyword k) v)
          m))
      {}
      (str/split params #"&"))) 
0.1s
Clojure
Map {:id: Vector(2), :token: "xyz"}

This of course ignores some important parts like decoding. Urls can also be a lot more tricky than the one above. Keep safe and happy hacking.

Runtimes (1)