Created
January 31, 2016 04:55
-
-
Save dydx/abb8ac0ac8e90aea5896 to your computer and use it in GitHub Desktop.
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
// Transducer (architect astronaut speak): | |
// * a powerful and composable way to build algorithmic transformations | |
// | |
// Transducer (laymans speak): | |
// * a generic and composable way to operate on a collection of values, | |
// * producing a new value or a new collection of values. | |
// | |
// The word transducer itself can be split into two parts that reflect | |
// this definition. | |
// | |
// * Transform - to produce some value from another | |
// * Reduce - to combine the values of a data structure to produce a new one | |
// | |
// to start with, here's an example that maps over an array to increment all | |
// its values | |
[1, 2, 3, 4].map((x) => x + 1); | |
// pretty simple. Note that two things are implicit here: | |
// * The return value is built up from a new, empty array | |
// * each value returned is added to the end of the new array as you | |
// would do manually using JavaScript's `concat` | |
// | |
// with this in mind, we can concert the example to use .reduce: | |
const concat = (a, b) => a.concat([b]); | |
console.log([1, 2, 3, 4] | |
.reduce((result, input) => concat(result, input + 1), [])); | |
const mapWithIncr = (collection) => | |
collection.reduce((result, input) => | |
concat(result, input + 1), []); | |
console.log(mapWithIncr([1, 2, 3, 4])); | |
// we can take this a step further toward generalization by passing the | |
// tranformation as a function | |
const inc = (x) => x + 1; | |
// using this with any collection requires another higher order function, map, | |
// that combines the transformation and the collection | |
// | |
// This is where things start to get interesting. This function contains the | |
// essence of what it means to map, we reduce on collection to another by | |
// transforming the values and concatenating the results together | |
// function map(transform, collection) { | |
// return collection.reduce(function (result, input) { | |
// return concat(result, transform(input)); | |
// }, []); | |
// } | |
const map = (transform, collection) => | |
collection.reduce((result, input) => | |
concat(result, transform(input)), []); | |
// in use it looks like this: | |
console.log(map(inc, [1, 2, 3, 4])); | |
// partially apply map with an incrementor | |
const mapIncr = (collection) => map(inc, collection); | |
console.log(mapIncr([1, 2, 3, 4])); | |
// now... to get a mapping function that partially applies | |
// the collection argument and accepts arguments to transform it.... | |
// ... basically, partially apply the second argument | |
// | |
const mapIncr2 = (f) => map(f, [1, 2, 3, 4]); | |
console.log(mapIncr2(inc)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment