Tailor keywordize implementation to concrete types

Even faster
This commit is contained in:
Ben Sless 2024-08-25 18:50:43 +03:00
parent 7ab6021630
commit dcb7258caf

View file

@ -1,52 +1,51 @@
(ns ^:no-doc reitit.walk) (ns ^:no-doc reitit.walk)
(defprotocol Walkable (defprotocol IKeywordize
(-walk [coll f])) (-keywordize [coll]))
(extend-protocol Walkable (defn- -keywordize-map
nil [m]
(-walk [_ _] nil) (persistent!
Object (reduce-kv
(-walk [x _] x) (fn [m k v]
clojure.lang.IMapEntry (if (string? k)
(-walk [e f] (clojure.lang.MapEntry. (f (.key e)) (f (.val e)))) (assoc! m (keyword k) (-keywordize v))
clojure.lang.ISeq (assoc! m (-keywordize k) (-keywordize v))))
(-walk [coll f] (map f coll)) (transient (empty m))
clojure.lang.PersistentList m)))
(-walk [coll f] (apply list (map f coll)))
clojure.lang.PersistentList$EmptyList
(-walk [x _] x)
clojure.lang.IRecord
(-walk [r f] (reduce (fn [r x] (conj r (f x))) r r)))
(defn- -walk-default (defn- -keywordize-default
[coll f] [coll]
(into (empty coll) (map f) coll)) (into (empty coll) (map -keywordize) coll))
(doseq [type [clojure.lang.PersistentArrayMap (doseq [type [clojure.lang.PersistentHashSet
clojure.lang.PersistentHashMap
clojure.lang.PersistentHashSet
clojure.lang.PersistentVector clojure.lang.PersistentVector
clojure.lang.PersistentQueue clojure.lang.PersistentQueue
clojure.lang.PersistentStructMap clojure.lang.PersistentStructMap
clojure.lang.PersistentTreeMap clojure.lang.PersistentTreeMap
clojure.lang.PersistentTreeSet]] clojure.lang.PersistentTreeSet]]
(extend type Walkable {:-walk -walk-default})) (extend type IKeywordize {:-keywordize -keywordize-default}))
(defn walk (doseq [type [clojure.lang.PersistentArrayMap
[inner outer form] clojure.lang.PersistentHashMap]]
(outer (-walk form inner))) (extend type IKeywordize {:-keywordize -keywordize-map}))
(defn postwalk [f form] (walk (partial postwalk f) f form)) (extend-protocol IKeywordize
nil
(-keywordize [_] nil)
Object
(-keywordize [x] x)
clojure.lang.MapEntry
(-keywordize [e] (clojure.lang.MapEntry/create
(-keywordize (.key e))
(-keywordize (.val e))))
clojure.lang.ISeq
(-keywordize [coll] (map -keywordize coll))
clojure.lang.PersistentList
(-keywordize [coll] (apply list (map -keywordize coll)))
clojure.lang.PersistentList$EmptyList
(-keywordize [x] x)
clojure.lang.IRecord
(-keywordize [r] (reduce (fn [r x] (conj r (-keywordize x))) r r)))
(defn- keywordize (defn keywordize-keys [m] (-keywordize m))
[m]
(persistent!
(reduce-kv
(fn [m k v] (if (string? k) (assoc! m (keyword k) v) m))
(transient {})
m)))
(defn keywordize-keys
[m]
(postwalk (fn [x] (if (map? x) (keywordize m) x)) m))