Skip to content

Instantly share code, notes, and snippets.

@danielneal
Last active November 4, 2018 18:49
Show Gist options
  • Save danielneal/74bcd39d2ae9686deea822adc5f813b9 to your computer and use it in GitHub Desktop.
Save danielneal/74bcd39d2ae9686deea822adc5f813b9 to your computer and use it in GitHub Desktop.
Compound - combining state and reducing functions
(ns compound2.core)
(defn no-op
([acc] acc)
([acc x] acc))
(defn connect
"Connects a tree of transducers together"
[[xf & xfs]]
(let [xfs (map #(if (vector? %) (connect %) %) xfs)]
(fn [rf]
(let [rf (xf (fn
([acc] acc)
([acc x]
(reduce (fn [acc xf]
((xf no-op) acc x)) acc xfs))))]
(fn
([] (rf))
([acc] (rf acc))
([acc x] (rf acc x)))))))
(defn transact [old c items]
(transduce c no-op old items))
(defn index [opts]
(let [{:keys [key-fn id]
:or {id key-fn}} opts]
(fn [rf]
(completing
(fn [acc x]
(let [[op item] x]
(case op
:add (let [k (key-fn item)
existing (get-in acc [id k])]
(if existing
(rf (update (rf (update acc id dissoc k) [:remove existing])
id assoc k item) [:add item])
(rf (update acc id assoc k item) [:add item])))
:remove (let [k (key-fn item)
existing (get-in acc [id k])]
(if existing
(rf (update acc id dissoc k) [:remove existing])
acc))
:remove-key (let [k item
existing (get-in acc [id k])]
(if existing
(rf (update acc id dissoc k) [:remove existing])
acc)))))))))
(def compound (c/connect [(index {:key-fn :a})
(index {:key-fn :name})])
(c/transact {} compound
[[:add {:a 1 :name "hi" :b 1 :type :product}]
[:add {:a 2 :name "there" :b 2 :type :product}]
[:add {:a 3 :name "what" :b 3 :type :person}]
[:add {:a 4 :name "banana" :b 4 :type :person}]
[:remove-key 1]])
;; {:a
;; {2 {:a 2, :name "there", :b 2, :type :product},
;; 3 {:a 3, :name "what", :b 3, :type :person},
;; 4 {:a 4, :name "banana", :b 4, :type :person}},
;; :name
;; {"there" {:a 2, :name "there", :b 2, :type :product},
;; "what" {:a 3, :name "what", :b 3, :type :person},
;; "banana" {:a 4, :name "banana", :b 4, :type :person}}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment