Skip to content

Instantly share code, notes, and snippets.

@christianromney
Last active May 27, 2016 11:27
Show Gist options
  • Save christianromney/5124373b0fe019e18c9e162bfb383c7c to your computer and use it in GitHub Desktop.
Save christianromney/5124373b0fe019e18c9e162bfb383c7c to your computer and use it in GitHub Desktop.
Functional Programming example: Implementing `map` in terms of `reduce`
// implementing map in terms of reduce
function count(coll) {
return (typeof coll === "undefined") ? 0 : coll.length;
}
function isEmpty(coll) {
return (0 === count(coll));
}
function first(coll) {
return isEmpty(coll) ? null : coll[0];
}
function rest(coll) {
return isEmpty(coll) ? [] : coll.slice(1);
}
function conj(coll, item) {
var copy = Array.from(coll);
copy.push(item);
return copy;
}
function reduce(f, init, coll) {
if (isEmpty(coll)) {
return init;
}
return reduce(f, f(init, first(coll)), rest(coll));
}
// the point of this gist
function map(f, coll) {
return reduce((acc, i) => conj(acc, f(i)), [], coll);
}
// some functions to play around with
function add(a, b) {
return a + b;
}
function inc(x) {
return x + 1;
}
// use it
reduce(add, 0, [1, 2, 3, 4, 5]);
map(inc, [0, 1, 2, 3]);
@christianromney
Copy link
Author

christianromney commented May 27, 2016

Note that reduce is implemented recursively here. This will overflow the stack without tail-call optimization for large enough collections, but it is the most straightforward implementation of the algorithm. The point of this gist is to illustrate the idea, not to produce production-quality code (besides, map and reduce are native now).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment