|
| 1 | +(ns flatland.ordered.map) |
| 2 | + |
| 3 | +(declare equiv-impl) |
| 4 | + |
| 5 | +(defn print-ordered-map [writer kvs ks opts] |
| 6 | + (pr-sequential-writer |
| 7 | + writer |
| 8 | + (fn [k w opts] |
| 9 | + (-write w \[) |
| 10 | + (-write w (pr-str k)) |
| 11 | + (-write w \space) |
| 12 | + (-write w (pr-str (get kvs k))) |
| 13 | + (-write w \])) |
| 14 | + "(" " " ")" |
| 15 | + opts |
| 16 | + ks)) |
| 17 | + |
| 18 | +(deftype OrderedMap [kvs ks] |
| 19 | + Object |
| 20 | + (toString [this] (pr-str* this)) |
| 21 | + (equiv [this that] (equiv-impl kvs that)) |
| 22 | + |
| 23 | + ;; js/map interface |
| 24 | + (keys [this] (es6-iterator ks)) |
| 25 | + (entries [this] (es6-entries-iterator (seq kvs))) |
| 26 | + (values [this] (es6-iterator (vals kvs))) |
| 27 | + (has [this k] (not (nil? (.get kvs k)))) |
| 28 | + (get [this k] (.get kvs k)) |
| 29 | + (forEach [this f] |
| 30 | + (doseq [k ks] |
| 31 | + (f k (get kvs k) this))) |
| 32 | + (forEach [this f use-as-this] |
| 33 | + (doseq [k ks] |
| 34 | + (.call f use-as-this k (get kvs k) this))) |
| 35 | + |
| 36 | + ;; js fallbacks |
| 37 | + (key_set [this] (to-array (keys kvs))) |
| 38 | + (entry_set [this] (to-array (map to-array kvs))) |
| 39 | + (value_set [this] (to-array (map val kvs))) |
| 40 | + |
| 41 | + ICloneable |
| 42 | + (-clone [_] (OrderedMap. kvs ks)) |
| 43 | + |
| 44 | + ;; IIterable |
| 45 | + ;; (-iterator [_] ) |
| 46 | + |
| 47 | + IWithMeta |
| 48 | + (-with-meta [this new-meta] |
| 49 | + (if (identical? (meta kvs) new-meta) |
| 50 | + this |
| 51 | + (OrderedMap. (with-meta kvs new-meta) ks))) |
| 52 | + |
| 53 | + IMeta |
| 54 | + (-meta [this] (meta kvs)) |
| 55 | + |
| 56 | + ICollection |
| 57 | + (-conj [coll entry] |
| 58 | + (if (vector? entry) |
| 59 | + (OrderedMap. (conj kvs entry) (if (contains? kvs (-nth entry 0)) |
| 60 | + ks |
| 61 | + (conj ks (-nth entry 0)))) |
| 62 | + (OrderedMap. (conj kvs entry) (into ks |
| 63 | + (comp (map #(-nth % 0)) |
| 64 | + (remove #(contains? kvs %))) |
| 65 | + entry)))) |
| 66 | + |
| 67 | + IEmptyableCollection |
| 68 | + (-empty [this] |
| 69 | + (if (seq ks) |
| 70 | + (OrderedMap. (-empty kvs) []) |
| 71 | + this)) |
| 72 | + |
| 73 | + IEquiv |
| 74 | + (-equiv [this that] (equiv-impl kvs that)) |
| 75 | + |
| 76 | + IHash |
| 77 | + (-hash [_] (hash kvs)) |
| 78 | + |
| 79 | + ISeqable |
| 80 | + (-seq [this] |
| 81 | + (when (seq ks) |
| 82 | + (map #(-find kvs %) ks))) |
| 83 | + |
| 84 | + IReversible |
| 85 | + (-rseq [this] |
| 86 | + (when (seq ks) |
| 87 | + (map #(-find kvs %) (rseq ks)))) |
| 88 | + |
| 89 | + ICounted |
| 90 | + (-count [this] (count kvs)) |
| 91 | + |
| 92 | + ILookup |
| 93 | + (-lookup [this attr] (-lookup kvs attr)) |
| 94 | + (-lookup [this attr not-found] (-lookup kvs attr not-found)) |
| 95 | + |
| 96 | + IAssociative |
| 97 | + (-assoc [coll k v] |
| 98 | + (OrderedMap. (assoc kvs k v) (if (contains? kvs k) |
| 99 | + ks |
| 100 | + (conj ks k)))) |
| 101 | + (-contains-key? [this k] |
| 102 | + (contains? kvs k)) |
| 103 | + |
| 104 | + IFind |
| 105 | + (-find [this k] |
| 106 | + (-find kvs k)) |
| 107 | + |
| 108 | + IMap |
| 109 | + (-dissoc [this k] |
| 110 | + (if (contains? kvs k) |
| 111 | + (OrderedMap. (dissoc kvs k) (into [] (remove #{k}) ks)) |
| 112 | + this)) |
| 113 | + |
| 114 | + IKVReduce |
| 115 | + (-kv-reduce [coll f init] |
| 116 | + (reduce |
| 117 | + (fn [acc k] |
| 118 | + (f acc k (get kvs k))) |
| 119 | + init |
| 120 | + ks)) |
| 121 | + |
| 122 | + IFn |
| 123 | + (-invoke [this k] (kvs k)) |
| 124 | + (-invoke [this k not-found] (kvs k not-found)) |
| 125 | + |
| 126 | + IPrintWithWriter |
| 127 | + (-pr-writer [_ writer opts] |
| 128 | + (-write writer "#ordered/map ") |
| 129 | + (print-ordered-map writer kvs ks opts))) |
| 130 | + |
| 131 | +(defn equiv-impl [kvs that] |
| 132 | + (= kvs (if (instance? OrderedMap that) |
| 133 | + (.-kvs that) |
| 134 | + that))) |
| 135 | + |
| 136 | +(def ^:private empty-ordered-map (OrderedMap. {} [])) |
| 137 | + |
| 138 | +(defn ordered-map |
| 139 | + ([] |
| 140 | + empty-ordered-map) |
| 141 | + ([coll] |
| 142 | + (into empty-ordered-map coll)) |
| 143 | + ([k v & kvs] |
| 144 | + (apply assoc empty-ordered-map k v kvs))) |
| 145 | + |
| 146 | +(comment |
| 147 | + (ordered-map :foo 123 :bar 456) |
| 148 | + ;; => #ordered/map [:foo 123, :bar 456] |
| 149 | + |
| 150 | + (conj (ordered-map :foo 123 :bar 456) [:baz 123]) |
| 151 | + ;; => #ordered/map [:foo 123, :bar 456, :baz 123] |
| 152 | + |
| 153 | + (assoc (ordered-map :foo 123 :bar 456) |
| 154 | + :baz 123 |
| 155 | + :baq 999) |
| 156 | + ;; => #ordered/map [:foo 123, :bar 456, :baz 123, :baq 999] |
| 157 | + |
| 158 | + (merge (ordered-map :foo 123 :bar 456) |
| 159 | + {:baz 123 |
| 160 | + :baq 999}) |
| 161 | + ;; => #ordered/map [:foo 123, :bar 456, :baz 123, :baq 999] |
| 162 | + |
| 163 | + (= (ordered-map :foo 123 :bar 456 :baz 123) |
| 164 | + {:foo 123 :bar 456 :baz 123}) |
| 165 | + ;; => true |
| 166 | + |
| 167 | + (= {:foo 123 :bar 456 :baz 123} |
| 168 | + (ordered-map :foo 123 :bar 456 :baz 123)) |
| 169 | + ;; => true |
| 170 | + |
| 171 | + (map? (ordered-map :foo 123 :bar 456 :baz 123)) |
| 172 | + ;; => true |
| 173 | + |
| 174 | + (empty (ordered-map :foo 123 :bar 456 :baz 123)) |
| 175 | + ;; => #ordered/map [] |
| 176 | + |
| 177 | + (ordered-map) |
| 178 | + ;; => #ordered/map [] |
| 179 | + |
| 180 | + (seq (ordered-map)) |
| 181 | + ;; => nil |
| 182 | + |
| 183 | + (reduce conj [] (ordered-map :foo 123 :bar 456 :baz 123)) |
| 184 | + ;; => [[:foo 123] [:bar 456] [:baz 123]] |
| 185 | + |
| 186 | + (keys (ordered-map :foo 123 :bar 456 :baz 123)) |
| 187 | + ;; => (:foo :bar :baz) |
| 188 | + |
| 189 | + (vals (ordered-map :foo 123 :bar 456 :baz 789)) |
| 190 | + ;; => (123 456 789) |
| 191 | + |
| 192 | + (meta (with-meta (ordered-map) {:foo :bar})) |
| 193 | + ;; => {:foo :bar} |
| 194 | + |
| 195 | + (-> (ordered-map) |
| 196 | + (assoc-in [:foo :bar] 1) |
| 197 | + (assoc-in [:foo :baz] 2)) |
| 198 | + |
| 199 | + (into (ordered-map) [[:foo 1] [:bar 2] [:foo 3]]) |
| 200 | + ;; #ordered/map [:foo 3, :bar 2] |
| 201 | + |
| 202 | + ) |
0 commit comments