diff --git a/src/clj/clojure/walk.clj b/src/clj/clojure/walk.clj index 0d9e0e1802..f4896dbdbf 100644 --- a/src/clj/clojure/walk.clj +++ b/src/clj/clojure/walk.clj @@ -90,21 +90,25 @@ the sorting function."} [form] (prewalk (fn [x] (print "Walked: ") (prn x) x) form)) +(defn transform-keys + "Recursively transform all map keys using f as a transformation function." + {:added "1.9"} + [m f] + (let [entry-f (fn [[k v]] [(f k) v])] + ;; only apply to maps + (postwalk (fn [x] (if (map? x) (into {} (map entry-f x)) x)) m))) + (defn keywordize-keys "Recursively transforms all map keys from strings to keywords." {:added "1.1"} [m] - (let [f (fn [[k v]] (if (string? k) [(keyword k) v] [k v]))] - ;; only apply to maps - (postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) m))) + (transform-keys m (fn [k] (if (string? k) (keyword k) k)))) (defn stringify-keys "Recursively transforms all map keys from keywords to strings." {:added "1.1"} [m] - (let [f (fn [[k v]] (if (keyword? k) [(name k) v] [k v]))] - ;; only apply to maps - (postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) m))) + (transform-keys m (fn [k] (if (keyword? k) (name k) k)))) (defn prewalk-replace "Recursively transforms form by replacing keys in smap with their diff --git a/test/clojure/test_clojure/clojure_walk.clj b/test/clojure/test_clojure/clojure_walk.clj index 115ae34318..a62522ebf6 100644 --- a/test/clojure/test_clojure/clojure_walk.clj +++ b/test/clojure/test_clojure/clojure_walk.clj @@ -14,6 +14,14 @@ (is (= (w/stringify-keys {:a 1, nil {:b 2 :c 3}, :d 4}) {"a" 1, nil {"b" 2 "c" 3}, "d" 4}))) +(deftest t-transform-keys + (is (= (w/transform-keys {:a 1, nil {:b 2 :c 3}, :d 4, :e 5} + (fn [k] + (if (keyword? k) + (str (name k) "-" (name k)) + k))) + {"a-a" 1, nil {"b-b" 2 "c-c" 3}, "d-d" 4, "e-e" 5}))) + (deftest t-prewalk-order (is (= (let [a (atom [])] (w/prewalk (fn [form] (swap! a conj form) form)