Last active
April 9, 2018 16:22
-
-
Save cap10morgan/bdcac0e5a56ac626d69d539d91dd0e7a to your computer and use it in GitHub Desktop.
Using Clojure transducers with maps
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Usually when doing a shallow transform on a map in Clojure I reach for `reduce-kv`, but when I have more than one reduce-kv | |
;; I start thinking I should use transducers instead. | |
;; So if I start with something like this: | |
(ns my.ns | |
(:require [clojure.edn :as edn])) | |
(defn strip-key-namespaces [m] | |
(reduce-kv | |
(fn [a k v] | |
(assoc a (-> k name keyword) v)) | |
{} m)) | |
(defn read-values [m] | |
(reduce-kv | |
(fn [a k v] | |
(assoc a k (edn/read-string v))) | |
{} m)) | |
(defn transform-map [m] | |
(-> m strip-key-namespaces read-values)) | |
;; I can convert it to use transducers like so: | |
(defn strip-key-namespace [[k v]] | |
[(-> k name keyword) v]))) | |
(defn read-value [[k v]] | |
[k (edn/read-string v)]))) | |
(defn transduce-map | |
([] {}) | |
([m] m) | |
([m [k v]] (assoc m k v))) | |
(transduce (comp (map strip-key-namespace) (map read-value)) | |
transduce-map | |
{:thingy/foo ":echo", :stuff/bar "2", :whee/baz "[\\a \\b \\c]"}) | |
; => {:foo :echo, :bar 2, :baz [\a \b \c]} | |
;; ...which a colleague pointed out could be simplified even further to this | |
;; (in place of the `transduce` call and eliminating the need for `transduce-map`): | |
(into {} (comp (map strip-key-namespace) (map read-value)) | |
{:thingy/foo ":echo", :stuff/bar "2", :whee/baz "[\\a \\b \\c]"}) | |
; also => {:foo :echo, :bar 2, :baz [\a \b \c]} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment