Last active
October 21, 2020 06:57
-
-
Save bsless/e76a6537907ad4eecd69dcb321318b95 to your computer and use it in GitHub Desktop.
Annotated version for Oded
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
(defn fold-by ;;; similar to group-by | |
([kf ;;; Key function to group on | |
op ;;; operation how to combine two elements under the same key | |
coll] ;; collection of maps | |
(persistent! | |
(reduce | |
(fn [ret x] ;; ret is a map from (kf x) to xs, similar to the result of group-by | |
(let [k (kf x) ;; derive the key | |
v (get ret k)] ;; get the value already associated with the key if it exists | |
(assoc! ret | |
k | |
(if (some? v) ;; if some value was found | |
(op v x) ;;; combine the found value with the new element from coll | |
(op x))))) ;; unary application, for completeness | |
(transient {}) ;;; go fast | |
coll)))) | |
(defn- map-combiner | |
[m] ;;; Takes a map of keyword -> function | |
(completing ;;; takes a function of [a b], returns a function that can also take one arg, like + and conj do. | |
(fn [m1 m2] ;; return a function of two maps | |
(reduce-kv ;;; reduce over the map of functions | |
(fn [acc k f] ;;; build up accumulator. at key `k` with function `f` | |
(let [v1 (get m1 k) ;;; get the values associated with `k` from m1 and m2 | |
v2 (get m2 k)] | |
(assoc acc k (f v1 v2)))) ;;; combine `v1` and `v2` with `f` and associate to `k` | |
{} | |
m)))) | |
(defn foldmaps | |
[idx ;;; index function | |
ops ;;; map of keywords -> functions | |
ms] ;;; coll of maps | |
(vals ;;; get back only the values | |
(fold-by ;;; returns a map | |
idx ;;; the index function to group-by | |
(map-combiner ops) ;;; Derive a function from the kw -> f map | |
ms))) | |
(def ms [{:a 1 :b "b"} {:a 2 :b "c"} {:a 3 :b "b"} {:a 4 :b "c"} {:a 3 :b "d"}]) | |
(defn- right [_ b] b) | |
(foldmaps :b {:a + :b right} ms) | |
;;; more sophisticated index: | |
(foldmaps (juxt :a :b) {:a + :b right} ms) | |
;;;; Expanded versions with rf's | |
(defn fold-by | |
([kf op coll] | |
(persistent! | |
(reduce | |
(fn [ret x] | |
(let [k (kf x) | |
v (get ret k)] | |
(assoc! ret k (if (some? v) | |
(op v x) | |
(op (op) x))))) | |
(transient {}) | |
coll)))) | |
(defn- map-combiner | |
[m] | |
(fn | |
([] | |
(reduce-kv | |
(fn [acc k f] | |
(assoc acc k (f))) | |
{} | |
m)) | |
([rec] | |
(reduce-kv | |
(fn [acc k f] | |
(let [v (get rec k)] | |
(assoc acc k (f v)))) | |
{} | |
m)) | |
([m1 m2] | |
(reduce-kv | |
(fn [acc k f] | |
(let [v1 (get m1 k) | |
v2 (get m2 k)] | |
(assoc acc k (f v1 v2)))) | |
{} | |
m)))) | |
(defn foldmaps | |
[idx ops ms] | |
(vals (fold-by idx (map-combiner ops) ms))) |
What is line 42 for?
What is line 42 for?
just some dumb accumulator.
Newer version needs all functions to have 0 and 2 arity, where 0 creates an initial value.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Wow man, thanks!!