|
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.") |
| 3 | + Prints like a normal Clojure map in the order of insertion." |
| 4 | + (:require [nextjournal.clerk.utils :as utils])) |
4 | 5 |
|
5 | 6 | (set! *warn-on-reflection* true) |
6 | 7 |
|
|
9 | 10 |
|
10 | 11 | (declare ->AlwaysArrayMap) |
11 | 12 |
|
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>")) |
| 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>"))) |
58 | 86 |
|
59 | 87 | (defn assoc-before [aam k v] |
60 | 88 | (->AlwaysArrayMap (apply array-map (list* k v (interleave (keys aam) (vals aam)))))) |
61 | 89 |
|
62 | 90 | (defn always-array-map [& kvs] |
63 | 91 | (->AlwaysArrayMap (apply array-map kvs))) |
64 | 92 |
|
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 "}")) |
| 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 "}"))) |
78 | 107 |
|
79 | 108 | (comment |
80 | 109 | (pr-str (always-array-map 1 2)) |
|
0 commit comments