Skip to content

Commit caec8d9

Browse files
authored
[Fix #43] Implement cljs version of ordered-map (#59)
- Add deps.edn for use with `:git/url` - Add cljs tests for map, make reader cross-platform - Change the map-test namespace to `cljc`, several sections are still marked as clj-only, because they rely on eval, hashCode, compact, or transient-map. I made some adjustments to the cljs implementation in the process to make it better match the clj version.
1 parent 1204452 commit caec8d9

File tree

10 files changed

+351
-105
lines changed

10 files changed

+351
-105
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,12 @@ pom.xml.asc
55
target
66
.lein*
77
docs
8+
tests.edn
9+
.cljs_node_repl
10+
.cpcache
11+
.dir-locals.el
12+
.nrepl-port
13+
node_modules
14+
out
15+
package-lock.json
16+
package.json

bin/kaocha

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env bash
2+
3+
[ -d node_modules/ws ] || npm install ws
4+
5+
clojure -A:test -M -m kaocha.runner "$@"

deps.edn

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{:paths ["src" "resources"]
2+
:deps {org.clojure/clojure {:mvn/version "1.10.3"}}
3+
:aliases
4+
{:test {:extra-paths ["test"]
5+
:extra-deps {lambdaisland/kaocha {:mvn/version "RELEASE"}
6+
lambdaisland/kaocha-cljs {:mvn/version "RELEASE"}
7+
org.clojure/clojurescript {:mvn/version "RELEASE"}}}}}

src/data_readers.clj

Lines changed: 0 additions & 2 deletions
This file was deleted.

src/data_readers.cljc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{ordered/set flatland.ordered.set/into-ordered-set
2+
ordered/map flatland.ordered.map/ordered-map-reader}

src/flatland/ordered/map.clj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,8 @@ assoc'ed for the first time. Supports transient."
206206
(defmethod print-method OrderedMap [o ^java.io.Writer w]
207207
(.write w "#ordered/map ")
208208
(print-method (seq o) w))
209+
210+
(defn ordered-map-reader [coll]
211+
(if (some-> (resolve 'cljs.env/*compiler*) deref)
212+
`(ordered-map ~(vec coll))
213+
(ordered-map coll)))

src/flatland/ordered/map.cljs

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
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

Comments
 (0)