add specialized MAP-VALS navigator to circumvent the unavoidable overhead of [ALL LAST]

This commit is contained in:
Nathan Marz 2016-06-06 16:03:08 -04:00
parent 9a9f425b7f
commit ae98aa48ba
4 changed files with 59 additions and 4 deletions

View file

@ -106,6 +106,7 @@
(reduce-kv (fn [m k v] (assoc m k (inc v))) {} data) (reduce-kv (fn [m k v] (assoc m k (inc v))) {} data)
(manual-similar-reduce-kv data) (manual-similar-reduce-kv data)
(transform [ALL LAST] inc data) (transform [ALL LAST] inc data)
(transform MAP-VALS inc data)
)) ))
(let [data (->> (for [i (range 1000)] [i i]) (into {}))] (let [data (->> (for [i (range 1000)] [i i]) (into {}))]
@ -114,6 +115,7 @@
(reduce-kv (fn [m k v] (assoc m k (inc v))) {} data) (reduce-kv (fn [m k v] (assoc m k (inc v))) {} data)
(manual-similar-reduce-kv data) (manual-similar-reduce-kv data)
(transform [ALL LAST] inc data) (transform [ALL LAST] inc data)
(transform MAP-VALS inc data)
)) ))

View file

@ -163,6 +163,14 @@
ALL ALL
(comp-paths (i/->AllNavigator))) (comp-paths (i/->AllNavigator)))
(defnav MAP-VALS []
(select* [this structure next-fn]
(doall (mapcat next-fn (vals structure))))
(transform* [this structure next-fn]
(i/map-vals-transform structure next-fn)
))
(def VAL (i/->ValCollect)) (def VAL (i/->ValCollect))
(def (def

View file

@ -702,6 +702,49 @@
(transform* [this structure next-fn] (transform* [this structure next-fn]
(all-transform structure next-fn))) (all-transform structure next-fn)))
(defprotocol MapValsTransformProtocol
(map-vals-transform [structure next-fn]))
(defn map-vals-non-transient-transform [structure empty-map next-fn]
(reduce-kv
(fn [m k v]
(assoc m k (next-fn v)))
empty-map
structure))
(extend-protocol MapValsTransformProtocol
#+clj clojure.lang.PersistentArrayMap #+cljs cljs.core/PersistentArrayMap
(map-vals-transform [structure next-fn]
(map-vals-non-transient-transform structure {} next-fn)
)
#+clj clojure.lang.PersistentTreeMap #+cljs cljs.core/PersistentTreeMap
(map-vals-transform [structure next-fn]
(map-vals-non-transient-transform structure (sorted-map) next-fn)
)
#+clj clojure.lang.PersistentHashMap #+cljs cljs.core/PersistentHashMap
(map-vals-transform [structure next-fn]
(persistent!
(reduce-kv
(fn [m k v]
(assoc! m k (next-fn v)))
(transient
#+clj clojure.lang.PersistentHashMap/EMPTY #+cljs cljs.core.PersistentHashMap.EMPTY
)
structure
)))
#+clj Object #+cljs default
(map-vals-transform [structure next-fn]
(reduce-kv
(fn [m k v]
(assoc m k (next-fn v)))
(empty structure)
structure))
)
(deftype ValCollect []) (deftype ValCollect [])
(extend-protocol p/Collector (extend-protocol p/Collector

View file

@ -64,8 +64,9 @@
(defspec select-all-on-map (defspec select-all-on-map
(for-all+ (for-all+
[m (limit-size 5 (gen/map gen/keyword gen/int))] [m (limit-size 5 (gen/map gen/keyword gen/int))
(= (select [s/ALL s/LAST] m) p (gen/elements [s/MAP-VALS [s/ALL s/LAST]])]
(= (select p m)
(for [[k v] m] v)) (for [[k v] m] v))
)) ))
@ -81,8 +82,9 @@
(defspec transform-all-on-map (defspec transform-all-on-map
(for-all+ (for-all+
[m (limit-size 5 (gen/map gen/keyword gen/int))] [m (limit-size 5 (gen/map gen/keyword gen/int))
(= (transform [s/ALL s/LAST] inc m) p (gen/elements [s/MAP-VALS [s/ALL s/LAST]])]
(= (transform p inc m)
(into {} (for [[k v] m] [k (inc v)])) (into {} (for [[k v] m] [k (inc v)]))
))) )))