Skip to content

Instantly share code, notes, and snippets.

@dydx
Created January 31, 2016 04:55
Show Gist options
  • Save dydx/abb8ac0ac8e90aea5896 to your computer and use it in GitHub Desktop.
Save dydx/abb8ac0ac8e90aea5896 to your computer and use it in GitHub Desktop.
// 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