|
1 | 1 | (ns nextjournal.clerk.always-array-map |
2 | 2 | "A persistent data structure that is based on array-map, but doesn't turn into a hash-map by using assoc etc. |
3 | | - Prints like a normal Clojure map in the order of insertion." |
4 | | - (:require [nextjournal.clerk.utils :as utils])) |
| 3 | + Prints like a normal Clojure map in the order of insertion.") |
5 | 4 |
|
6 | 5 | (set! *warn-on-reflection* true) |
7 | 6 |
|
|
10 | 9 |
|
11 | 10 | (declare ->AlwaysArrayMap) |
12 | 11 |
|
13 | | -(utils/if-bb |
14 | | - (defn ->AlwaysArrayMap [m] |
15 | | - (proxy [clojure.lang.APersistentMap clojure.lang.IMeta clojure.lang.IObj] |
16 | | - [] |
17 | | - (valAt |
18 | | - ([k] |
19 | | - (get m k)) |
20 | | - ([k default-value] |
21 | | - (get m k default-value))) |
22 | | - (iterator [] |
23 | | - (.iterator ^java.lang.Iterable m)) |
24 | | - |
25 | | - (containsKey [k] (contains? m k)) |
26 | | - (entryAt [k] (when (contains? m k) |
27 | | - (get this k))) |
28 | | - (equiv [other] (= m other)) |
29 | | - (empty [] (empty m)) |
30 | | - (count [] (count m)) |
31 | | - (assoc [k v] (if (< (count m) 8) |
32 | | - (->AlwaysArrayMap (assoc m k v)) |
33 | | - (->AlwaysArrayMap (assoc-after m k v)))) |
34 | | - (without [k] (->AlwaysArrayMap (dissoc m k))) |
35 | | - (seq [] (seq m)) |
36 | | - ; a lot of map users expect meta to work |
37 | | - (meta [] (meta m)) |
38 | | - (withMeta [meta] (->AlwaysArrayMap (with-meta m meta))))) |
39 | | - |
40 | | - (deftype AlwaysArrayMap [^clojure.lang.PersistentArrayMap the-map] |
41 | | - clojure.lang.ILookup |
42 | | - (valAt [_ k] |
43 | | - (get the-map k)) |
44 | | - |
45 | | - clojure.lang.Seqable |
46 | | - (seq [_] |
47 | | - (seq the-map)) |
48 | | - |
49 | | - clojure.lang.IPersistentMap |
50 | | - (assoc [_ k v] |
51 | | - (if (< (count the-map) 8) |
52 | | - (->AlwaysArrayMap (assoc the-map k v)) |
53 | | - (->AlwaysArrayMap (assoc-after the-map k v)))) |
54 | | - |
55 | | - (assocEx [_ _k _v] |
56 | | - (throw (ex-info "Not implemented" {}))) |
57 | | - |
58 | | - (without [_ k] |
59 | | - (->AlwaysArrayMap (dissoc the-map k))) |
60 | | - |
61 | | - clojure.lang.Associative |
62 | | - (containsKey [_ k] |
63 | | - (contains? the-map k)) |
64 | | - |
65 | | - clojure.lang.IPersistentCollection |
66 | | - (equiv [_ other] |
67 | | - (= the-map other)) |
68 | | - (count [_] |
69 | | - (count the-map)) |
70 | | - |
71 | | - java.lang.Iterable |
72 | | - (iterator [_] |
73 | | - (.iterator the-map)) |
74 | | - |
75 | | - clojure.lang.IMeta |
76 | | - (meta [_] |
77 | | - (meta the-map)) |
78 | | - |
79 | | - clojure.lang.IObj |
80 | | - (withMeta [_ meta] |
81 | | - (->AlwaysArrayMap (with-meta the-map meta))) |
82 | | - |
83 | | - Object |
84 | | - (toString [_] |
85 | | - "<always-array-map>"))) |
| 12 | +(deftype AlwaysArrayMap [^clojure.lang.PersistentArrayMap the-map] |
| 13 | + clojure.lang.ILookup |
| 14 | + (valAt [_ k] |
| 15 | + (get the-map k)) |
| 16 | + |
| 17 | + clojure.lang.Seqable |
| 18 | + (seq [_] |
| 19 | + (seq the-map)) |
| 20 | + |
| 21 | + clojure.lang.IPersistentMap |
| 22 | + (assoc [_ k v] |
| 23 | + (if (< (count the-map) 8) |
| 24 | + (->AlwaysArrayMap (assoc the-map k v)) |
| 25 | + (->AlwaysArrayMap (assoc-after the-map k v)))) |
| 26 | + |
| 27 | + (assocEx [_ _k _v] |
| 28 | + (throw (ex-info "Not implemented" {}))) |
| 29 | + |
| 30 | + (without [_ k] |
| 31 | + (->AlwaysArrayMap (dissoc the-map k))) |
| 32 | + |
| 33 | + clojure.lang.Associative |
| 34 | + (containsKey [_ k] |
| 35 | + (contains? the-map k)) |
| 36 | + |
| 37 | + clojure.lang.IPersistentCollection |
| 38 | + (equiv [_ other] |
| 39 | + (= the-map other)) |
| 40 | + (count [_] |
| 41 | + (count the-map)) |
| 42 | + |
| 43 | + java.lang.Iterable |
| 44 | + (iterator [_] |
| 45 | + (.iterator the-map)) |
| 46 | + |
| 47 | + clojure.lang.IMeta |
| 48 | + (meta [_] |
| 49 | + (meta the-map)) |
| 50 | + |
| 51 | + clojure.lang.IObj |
| 52 | + (withMeta [_ meta] |
| 53 | + (->AlwaysArrayMap (with-meta the-map meta))) |
| 54 | + |
| 55 | + Object |
| 56 | + (toString [_] |
| 57 | + "<always-array-map>")) |
86 | 58 |
|
87 | 59 | (defn assoc-before [aam k v] |
88 | 60 | (->AlwaysArrayMap (apply array-map (list* k v (interleave (keys aam) (vals aam)))))) |
89 | 61 |
|
90 | 62 | (defn always-array-map [& kvs] |
91 | 63 | (->AlwaysArrayMap (apply array-map kvs))) |
92 | 64 |
|
93 | | -(utils/when-not-bb |
94 | | - (defmethod print-method AlwaysArrayMap |
95 | | - [v ^java.io.Writer writer] |
96 | | - (.write writer "{") |
97 | | - (let [write-kv! (fn [k v] |
98 | | - (.write writer (pr-str k)) |
99 | | - (.write writer " ") |
100 | | - (.write writer (pr-str v)))] |
101 | | - (doseq [[k v] (butlast v)] |
102 | | - (write-kv! k v) |
103 | | - (.write writer ", ")) |
104 | | - (let [[k v] (last v)] |
105 | | - (write-kv! k v))) |
106 | | - (.write writer "}"))) |
| 65 | +(defmethod print-method AlwaysArrayMap |
| 66 | + [v ^java.io.Writer writer] |
| 67 | + (.write writer "{") |
| 68 | + (let [write-kv! (fn [k v] |
| 69 | + (.write writer (pr-str k)) |
| 70 | + (.write writer " ") |
| 71 | + (.write writer (pr-str v)))] |
| 72 | + (doseq [[k v] (butlast v)] |
| 73 | + (write-kv! k v) |
| 74 | + (.write writer ", ")) |
| 75 | + (let [[k v] (last v)] |
| 76 | + (write-kv! k v))) |
| 77 | + (.write writer "}")) |
107 | 78 |
|
108 | 79 | (comment |
109 | 80 | (pr-str (always-array-map 1 2)) |
|
0 commit comments