-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.clj
37 lines (34 loc) · 1.4 KB
/
utils.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
(ns common-clj.lib.utils
(:require [clojure.walk :refer [postwalk prewalk prewalk-demo postwalk-demo]]))
(defmacro for-map
"Like 'for' for building maps. Same bindings except the body should have a
key-expression and value-expression. If a key is repeated, the last
value (according to \"for\" semantics) will be retained.
(= (for-map [i (range 2) j (range 2)] [i j] (even? (+ i j)))
{[0 0] true, [0 1] false, [1 0] false, [1 1] true})
An optional symbol can be passed as a first argument, which will be
bound to the transient map containing the entries produced so far."
([seq-exprs key-expr val-expr]
`(for-map ~(gensym "m") ~seq-exprs ~key-expr ~val-expr))
([m-sym seq-exprs key-expr val-expr]
`(let [m-atom# (atom (transient {}))]
(doseq ~seq-exprs
(let [~m-sym @m-atom#]
(reset! m-atom# (assoc! ~m-sym ~key-expr ~val-expr))))
(persistent! @m-atom#))))
(defn map-vals
"Build map k -> (f v) for [k v] in map, preserving the initial type"
[f m]
(cond
(sorted? m)
(reduce-kv (fn [out-m k v] (assoc out-m k (f v))) (sorted-map) m)
(map? m)
(persistent! (reduce-kv (fn [out-m k v] (assoc! out-m k (f v))) (transient {}) m))
:else
(for-map [[k v] m] k (f v))))
(defn vectorize
"Recursively transforms all seq in m to vectors.
Because maybe you want to use core.match with it."
[x]
(postwalk #(if (seq? %) (vec %) %)
x))