Skip to content

Commit feace80

Browse files
joshlemerpuredanger
authored andcommitted
DIMAP-17 empty int-map/int-set/dense-int-set are singleton instances
1 parent 3055349 commit feace80

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

src/main/clojure/clojure/data/int_map.clj

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
then
4646
else))
4747

48-
(declare ->transient-int-map)
48+
(declare ->transient-int-map
49+
^:private EMPTY-INT-MAP)
4950

5051
(deftype PersistentIntMap
5152
[^INode root
@@ -292,6 +293,8 @@
292293
(invoke [this k default]
293294
(.valAt this k default)))
294295

296+
(def ^:private ^PersistentIntMap EMPTY-INT-MAP (PersistentIntMap. Nodes$Empty/EMPTY 0 nil))
297+
295298
(deftype TransientIntMap
296299
[^INode root
297300
^long epoch
@@ -396,16 +399,16 @@
396399
"Given alternating keys and values, creates an integer map that can only
397400
have non-negative integers as keys."
398401
([]
399-
(PersistentIntMap. Nodes$Empty/EMPTY 0 nil))
402+
EMPTY-INT-MAP)
400403
([a b]
401-
(assoc (int-map) a b))
404+
(assoc EMPTY-INT-MAP a b))
402405
([a b & rest]
403-
(apply assoc (int-map) a b rest)))
406+
(apply assoc EMPTY-INT-MAP a b rest)))
404407

405408
(defn merge-with
406409
"Merges together two int-maps, using `f` to resolve value conflicts."
407410
([f]
408-
(int-map))
411+
EMPTY-INT-MAP)
409412
([f a b]
410413
(let [a' (if (instance? TransientIntMap a)
411414
(persistent! a)
@@ -420,7 +423,7 @@
420423
(defn merge
421424
"Merges together two int-maps, giving precedence to values from the right-most map."
422425
([]
423-
(int-map))
426+
EMPTY-INT-MAP)
424427
([a b]
425428
(merge-with (fn [_ b] b) a b))
426429
([a b & rest]
@@ -576,23 +579,26 @@
576579

577580
;;;
578581

582+
(def ^:private ^PersistentIntSet EMPTY-INT-SET (PersistentIntSet. (IntSet. 128) 0 nil))
583+
(def ^:private ^PersistentIntSet EMPTY-DENSE-INT-SET (PersistentIntSet. (IntSet. 4096) 0 nil))
584+
579585
(defn int-set
580586
"Given a collection, creates an immutable set which can only store integral values.
581587
This should be used unless elements are densely clustered (each element has multiple
582588
elements within +/- 1000)."
583589
([]
584-
(PersistentIntSet. (IntSet. 128) 0 nil))
590+
EMPTY-INT-SET)
585591
([s]
586-
(into (int-set) s)))
592+
(into EMPTY-INT-SET s)))
587593

588594
(defn dense-int-set
589595
"Given a collection, creates an immutable set which can only store integral values.
590596
This should be used only if elements are densely clustered (each element has multiple
591597
elements within +/- 1000)."
592598
([]
593-
(PersistentIntSet. (IntSet. 4096) 0 nil))
599+
EMPTY-DENSE-INT-SET)
594600
([s]
595-
(into (dense-int-set) s)))
601+
(into EMPTY-DENSE-INT-SET s)))
596602

597603
(defn union
598604
"Returns the union of two bitsets."

src/test/clojure/clojure/data/int_map_test.clj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,3 +303,10 @@
303303

304304
(defspec prop-dense-all-set-algebra-operators-equivalent 1e5
305305
(all-set-algebra-operators-equivalent? i/dense-int-set))
306+
307+
(deftest int-map-empty-singleton
308+
(is (identical? (i/int-map) (i/int-map)) "(int-map) should always return the same instance"))
309+
(deftest int-set-empty-singleton
310+
(is (identical? (i/int-set) (i/int-set)) "(int-set) should always return the same instance"))
311+
(deftest dense-int-set-empty-singleton
312+
(is (identical? (i/dense-int-set) (i/dense-int-set)) "(dense-int-set) should always return the same instance"))

0 commit comments

Comments
 (0)