JavaScript supports first-class functions which makes a lot of
functional programming easy.
With ES5, JavaScript has built-in support for
functional programming constructs like a .map()
&
.reduce()
.
Here are some fun snippets to demonstrate functional programming concepts with JavaScript.
Based on exercises from 4Clojure.
.reduce()
function parseBinary(str) {
return str.split('').reduce(function(a, b) {
return a * 2 + (b === '0' ? 0 : 1);
}, 0);
}
parseBinary('0000') -> 0
parseBinary('0001') -> 1
parseBinary('111') -> 7
parseBinary('1000') -> 8
This function takes an array and groups all the items
from the array that have the same value for fn(item)
.
Reduce can solve any problem that can be solved by tail recursion.
function groupBy(arr, fn) {
arr = arr.slice(); // clone so we don't modify array in place
// sort items so items that have the same fn(item) are
// adjacent
arr.sort(function(a, b) {
return fn(a) > fn(b) ? 1 : -1;
});
return arr.reduce(function(out, item) {
if (! out.length) {
return [[item]]
}
if (fn(out[out.length - 1][0]) === fn(item)) {
out[out.length - 1].push(item);
return out;
}
out.push([item]);
return out;
}, []);
}
Without operator precedence. With .reduce()
and
using _.groupBy()
.
function pairs(items) {
var result = _.groupBy(items, function(item, i) {
return Math.floor(i / 2);
});
return _.values(result);
}
function calc(expression) {
var tokens = expression.split(' ');
var n = parseInt(tokens[0]);
tokens = tokens.slice(1);
return pairs(tokens).reduce(function(tot, oper) {
if (oper[0] === '+') {
return tot + parseInt(oper[1]);
} else if (oper[0] === '-') {
return tot - parseInt(oper[1]);
} else if (oper[0] === '/') {
return tot / parseInt(oper[1]);
} else if (oper[0] === '*') {
return tot * parseInt(oper[1]);
}
}, n);
}
calc('1 + 2 * 4 / 1 / 12 - 8') -> -7
This function takes an array of words and groups every word that is an anagram of eachother together.
function anagrams(arr) {
return _.values(_.groupBy(arr, function(word) {
var letters = word.split('');
letters.sort();
return letters.join('');
}))
}
anagrams(['aba', 'baa', 'aab', 'c']) -> [['aba', 'baa', 'aab'], ['c']]
anagrams(['aab', 'aba', 'xy', 'xy']) -> [['aab', 'aba'], ['xy', 'xy']]