/
collections.clj
61 lines (52 loc) · 1.52 KB
/
collections.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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
(ns contextual.impl.collections
(:require
[contextual.impl.protocols :as p]))
(defrecord MapWrapper [m]
p/IContext
(-invoke [this ctx]
(persistent!
(reduce-kv
(fn [m k v]
(assoc! m (p/-invoke k ctx) (p/-invoke v ctx)))
(transient {})
m))))
(defonce ^:private map-wrapper-builders (atom {}))
(defmacro ^:private def-map-wrappers []
(let [invoke '-invoke
ctx 'ctx
name "MapWrapper"
defs
(for [n (range 1 13)
:let [ks (map (comp symbol #(str "k" %)) (range n))
vs (map (comp symbol #(str "v" %)) (range n))
rec (symbol (str name n))
constructor (symbol (str "->" rec))
body (reduce-kv
(fn [m k v]
(assoc m `(p/-invoke ~k ~ctx) `(p/-invoke ~v ~ctx)))
{}
(zipmap ks vs))]]
`(do
(defrecord ~rec [~@(interleave ks vs)]
p/IContext
(~invoke [~'this ~ctx]
~body))
(swap! map-wrapper-builders assoc ~n ~constructor)))]
`(do
~@defs)))
(def-map-wrappers)
(defn ->map
[m]
(let [n (count m)
args (mapcat identity m)
c (get @map-wrapper-builders n)]
(if c
(apply c args)
(->MapWrapper m))))
(comment
(->map {:a 1 :b 2}))
(defrecord VectorWrapper [v]
p/IContext
(-invoke [this ctx]
(into [] (map p/-invoke) v)))
(defn ->vector [v] (->VectorWrapper v))