Skip to content

Commit 5560276

Browse files
committed
PersistentHashSet and Transient support
1 parent a5a1f94 commit 5560276

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

src/cljc/cljc/core.cljc

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313

1414
(def EMPTY nil)
1515

16+
(ns cljc.core.PersistentHashSet)
17+
18+
(def EMPTY nil)
19+
(def fromArray nil)
20+
1621
(ns cljc.core.List)
1722

1823
(def EMPTY nil)
@@ -1001,6 +1006,15 @@ reduces them without incurring seq initialization"
10011006
(next s)))
10021007
h)))
10031008

1009+
(defn- hash-iset [s]
1010+
;; a la clojure.lang.APersistentSet
1011+
(loop [h 0 s (seq s)]
1012+
(if s
1013+
(let [e (first s)]
1014+
(recur (mod (+ h (hash e)) 4503599627370496)
1015+
(next s)))
1016+
h)))
1017+
10041018
(defn ^boolean every?
10051019
"Returns true if (pred x) is logical true for every x in coll, else
10061020
false."
@@ -1218,6 +1232,15 @@ reduces them without incurring seq initialization"
12181232
(recur (next in) (conj out (first in)))
12191233
out)))
12201234

1235+
(defn hash-set
1236+
([] cljc.core.PersistentHashSet/EMPTY)
1237+
([& keys]
1238+
(loop [in (seq keys)
1239+
out (transient cljc.core.PersistentHashSet/EMPTY)]
1240+
(if (seq in)
1241+
(recur (next in) (conj! out (first in)))
1242+
(persistent! out)))))
1243+
12211244
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Strings ;;;;;;;;;;;;;;;;
12221245

12231246
(declare split-string-seq-next-fn)
@@ -2779,6 +2802,143 @@ reduces them without incurring seq initialization"
27792802
ITransientMap
27802803
(-dissoc! [tcoll key] (-without! tcoll key)))
27812804

2805+
(defn hash-map
2806+
"keyval => key val
2807+
Returns a new hash map with supplied mappings."
2808+
[& keyvals]
2809+
(loop [in (seq keyvals), out (transient cljc.core.PersistentHashMap/EMPTY)]
2810+
(if in
2811+
(recur (nnext in) (assoc! out (first in) (second in)))
2812+
(persistent! out))))
2813+
2814+
(defn keys
2815+
"Returns a sequence of the map's keys."
2816+
[hash-map]
2817+
(seq (map first hash-map)))
2818+
2819+
(defn key
2820+
"Returns the key of the map entry."
2821+
[map-entry]
2822+
(-key map-entry))
2823+
2824+
(defn vals
2825+
"Returns a sequence of the map's values."
2826+
[hash-map]
2827+
(seq (map second hash-map)))
2828+
2829+
(defn val
2830+
"Returns the value in the map entry."
2831+
[map-entry]
2832+
(-val map-entry))
2833+
2834+
2835+
;;; PersistentHashSet
2836+
2837+
(declare TransientHashSet)
2838+
2839+
(deftype PersistentHashSet [meta hash-map ^:mutable __hash]
2840+
IWithMeta
2841+
(-with-meta [coll meta] (PersistentHashSet. meta hash-map __hash))
2842+
2843+
IMeta
2844+
(-meta [coll] meta)
2845+
2846+
ICollection
2847+
(-conj [coll o]
2848+
(PersistentHashSet. meta (assoc hash-map o nil) nil))
2849+
2850+
IEmptyableCollection
2851+
(-empty [coll] (-with-meta cljc.core.PersistentHashSet/EMPTY meta))
2852+
2853+
IEquiv
2854+
(-equiv [coll other]
2855+
(and
2856+
(set? other)
2857+
(== (count coll) (count other))
2858+
(every? #(contains? coll %)
2859+
other)))
2860+
2861+
IHash
2862+
(-hash [coll] (caching-hash coll hash-iset __hash))
2863+
2864+
ISeqable
2865+
(-seq [coll] (keys hash-map))
2866+
2867+
ICounted
2868+
(-count [coll] (count (seq coll)))
2869+
2870+
ILookup
2871+
(-lookup [coll v]
2872+
(-lookup coll v nil))
2873+
(-lookup [coll v not-found]
2874+
(if (-contains-key? hash-map v)
2875+
v
2876+
not-found))
2877+
2878+
ISet
2879+
(-disjoin [coll v]
2880+
(PersistentHashSet. meta (dissoc hash-map v) nil))
2881+
2882+
IFn
2883+
(-invoke [coll k]
2884+
(-lookup coll k))
2885+
(-invoke [coll k not-found]
2886+
(-lookup coll k not-found))
2887+
2888+
IEditableCollection
2889+
(-as-transient [coll] (TransientHashSet. (transient hash-map)))
2890+
2891+
IPrintable
2892+
(-pr-seq [coll opts] (pr-sequential pr-seq "#{" " " "}" opts coll)))
2893+
2894+
(set! cljc.core.PersistentHashSet/EMPTY (PersistentHashSet. nil (hash-map) 0))
2895+
2896+
(set! cljc.core.PersistentHashSet/fromArray
2897+
(fn [items]
2898+
(let [len (count items)]
2899+
(loop [i 0
2900+
out (transient cljc.core.PersistentHashSet/EMPTY)]
2901+
(if (< i len)
2902+
(recur (inc i) (conj! out (aget items i)))
2903+
(persistent! out))))))
2904+
2905+
(deftype TransientHashSet [^:mutable transient-map]
2906+
ITransientCollection
2907+
(-conj! [tcoll o]
2908+
(set! transient-map (assoc! transient-map o nil))
2909+
tcoll)
2910+
2911+
(-persistent! [tcoll]
2912+
(PersistentHashSet. nil (persistent! transient-map) nil))
2913+
2914+
ITransientSet
2915+
(-disjoin! [tcoll v]
2916+
(set! transient-map (dissoc! transient-map v))
2917+
tcoll)
2918+
2919+
ICounted
2920+
(-count [tcoll] (count transient-map))
2921+
2922+
ILookup
2923+
(-lookup [tcoll v]
2924+
(-lookup tcoll v nil))
2925+
2926+
(-lookup [tcoll v not-found]
2927+
(if (identical? (-lookup transient-map v lookup-sentinel) lookup-sentinel)
2928+
not-found
2929+
v))
2930+
2931+
IFn
2932+
(-invoke [tcoll k]
2933+
(if (identical? (-lookup transient-map k lookup-sentinel) lookup-sentinel)
2934+
nil
2935+
k))
2936+
2937+
(-invoke [tcoll k not-found]
2938+
(if (identical? (-lookup transient-map k lookup-sentinel) lookup-sentinel)
2939+
not-found
2940+
k)))
2941+
27822942
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; main function support ;;;;;;;;;;;;;;;;
27832943

27842944
(defn vector-from-c-string-array [argc argv]

0 commit comments

Comments
 (0)