patternjavascriptMinor
FizzBuzz functional implementation
Viewed 0 times
functionalimplementationfizzbuzz
Problem
I was playing around with ES6 arrow functions, currying and partial application and I decided to try a functional implementation of the FizzBuzz problem:
My main focus was to be able to easily add any other case like "print Zazz for numbers lower than 10" by simply adding
What do you think?
function* range(start, stop) {
for (var i = start; i res => x => fn(x) ? res : null
var isDividedBy = dividend => divisor => divisor % dividend === 0
var mapDividedBy = x => map(isDividedBy(x))
var mappers = [
mapDividedBy(3)('Fizz'),
mapDividedBy(5)('Buzz')
]
var applyMappers = mappers => x => mappers.map(fn => fn(x)).join('') || x
var result = Array.from(range(1, 100)).map(applyMappers(mappers))
console.log(result)My main focus was to be able to easily add any other case like "print Zazz for numbers lower than 10" by simply adding
map(x => x < 10)('Zazz') to the mappers array.What do you think?
Solution
map vs ifvar map = fn => res => x => fn(x) ? res : nullI would rename this to something more like
ifThen or when -- calling this function map is confusing, to me at least, given the normal usage of map. This is an if where the else is always null.In a larger program you may find that providing the true/false results as functions instead of constants would be more powerful, but here that would just add noise.
const
Most of your
vars could be consts. Doesn't make much difference here but since you're deliberately being functional const would help declare your intent.without
mapDividedByI don't think you need this specialized function. Just pass the predicate and true-result into your
when/if:const when = pred => trueRes => x => pred(x) ? trueRes : null
const isDividedBy = dividend => divisor => divisor % dividend === 0
const mappers = [
when(isDividedBy(3))('Fizz'),
when(isDividedBy(5))('Buzz'),
]naming
I'm not sure
mappers is the most descriptive name. I can't think of anything better at present, so that's not very helpful, but any (pure) function is just a "mapper" from inputs to output(s). Maybe tests? Hmm.In any event, since this is a FizzBuzz I suggest providing a final function named as such, for convenience and readability:
const fizzbuzz = applyMappers(mappers)
const result = Array.from(range(1, 100)).map(fizzbuzz)misc
I like your currying approach.
Clojure has a function
juxt which does the same thing as mappers.map(fn => fn(x)) but looks a little cleaner, being a separate function:const fizzbuzz = x => juxt(mappers)(x).join('') || xBut whether this is more readable or more obscure depends on whether you know Clojure, so I've left this point to the end.
Code Snippets
var map = fn => res => x => fn(x) ? res : nullconst when = pred => trueRes => x => pred(x) ? trueRes : null
const isDividedBy = dividend => divisor => divisor % dividend === 0
const mappers = [
when(isDividedBy(3))('Fizz'),
when(isDividedBy(5))('Buzz'),
]const fizzbuzz = applyMappers(mappers)
const result = Array.from(range(1, 100)).map(fizzbuzz)const fizzbuzz = x => juxt(mappers)(x).join('') || xContext
StackExchange Code Review Q#115743, answer score: 3
Revisions (0)
No revisions yet.