Created
March 1, 2017 15:56
-
-
Save odyss009/05a9e5f0773f2c09accacd1083e1de24 to your computer and use it in GitHub Desktop.
filterReducer, mapReducer, composeReducers, transducer
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
// Count the iterations | |
let count = 0; | |
const isMultipleOf3Or5 = n => (n % 3 === 0 || n % 5 === 0); | |
// Reducer functions can be composed if we abstract the differences. | |
// The filter's predicate function will need to be abstracted | |
// and curried in for function composition: | |
const filterReducer = predicate => reducer => ( | |
acc, item | |
) => predicate(item) ? reducer(acc, item) : acc; | |
// The mapping function needs to be abstracted and curried in | |
// to make a map reducer composable: | |
const mapReducer = mapper => reducer => ( | |
acc, item | |
) => { | |
count++; | |
return reducer(acc, mapper(item)); | |
}; | |
// A shared reducing function abstracts how individual values | |
// get accumulated together: | |
const arrReducer = (acc = [], item) => acc.concat([item]); | |
const double = x => x * 2; | |
// Generic function composition | |
const compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x); | |
// Compose curried reducers, passing in the shared | |
// reducing function. The returned reducer can be directly used | |
// by any standard reduce() utility: | |
const composeReducers = reducingFn => (...fns) => compose(...fns)(reducingFn); | |
// Create a transducer: A function which can feed values | |
// through multiple reducers without traversing the collection | |
// more than once. If you filter the collection in a previous | |
// step, the total work will not exceed the size of the filtered | |
// set. | |
const transducer = composeReducers(arrReducer)( | |
filterReducer(isMultipleOf3Or5), | |
mapReducer(x => x + 1), | |
); | |
// Usage | |
const range = (start, end) => Array.from({ length: end - start + 1 }, (x, i) => i + start); | |
const doubled = range(1,9) | |
.reduce(transducer, []); | |
console.log(doubled, count); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment