There is a way to write "pure functional" FizzBuzz, without accumulating or checking the condition twice. Since all of the answers so far use 2+ if
statements, here's my version:
function fizzbuzz(n) {
const test = (divisor, callout, f) => (n % divisor === 0) ?
() => callout + f('') :
f;
const fizz = test.bind(this, 3, 'Fizz');
const buzz = test.bind(this, 5, 'Buzz');
return fizz(buzz(x => x))(n);
}
document.write(Array(100).fill().map((_, i) => fizzbuzz(i + 1)));
Source: https://youtu.be/dC9vdQkU-xI?t=25m9s
It's hard to explain, so let's consider trivial example with only "Fizz" part. I also removed arrow functions and conditional operators, for clarity.
function fizz(n) {
const fizzer = function(f) {
if (n % 3 === 0) {
return function() {
return 'Fizz' + f('');
};
} else {
return f;
}
};
const identityFunction = function(x) {
return x;
};
return fizzer(identityFunction)(n);
}
In this example, execution can only go in one of two ways:
n % 3 !== 0
- we return passed function fromfizzer
n % 3 === 0
- we get "Fizz", and execution of passed function with empty string
Passed function is identityFunction
, therefore in first case we get the number - (n)
.
Second part of second case is optional, but it's where the magic happens when we chain more functions. If you want to better understand what's going on - try removing f('')
or changing it to f('Abc')
or f
. Or try changing last return
to return fizzer(fizzer(identityFunction))(n);