In the last article we have made progress by using a more modern syntax.
All of this is fine and dandy, but it’s also very 2016. Functional programming is a coding paradigm that’s considered safer and more modern.
Now I’m not going to get into the nitty gritty of functional programming, but in our case we should consider the following rules:
Whatever we do it should be within a function. Check.
Given the same input (parameters) our function should always return the same value. Check.
Our function should not affect any external data (pure function). Check.
Our function should be as readable and reusable as possible. Not yet.
Why we should rethink our code? Because of two things related to the same thing.
Take a look at the for loop. It serves for multiple purposes:
It is used to make our array grow by iterating.
Its iterator (variable i) is used for checking FizzBuzz conditions.
Let’s look at the general problem from a different perspective. We’ll describe it this way:
- Instead of adding numbers to an empty array, let’s create an array of numbers the length of which is defined by the input.
- Let’s use given array to create a new array by examining each value and replacing it when necessary with Fizz/Buzz.
- Since creating a base array and returning a FizzBuzz array are two separate things, we’ll keep the principle of separation of concerns (SoC) and split the tasks into separate functions.
Let’s do just that.
I have created a local helper variable “curVal”, since our index doesn’t correspond to the current array value anymore.
Another thing should bug anyone who’s into functional programming are the two loops. While perfectly fine they can be replaced by more modern methods of iterating arrays.
So let’s fix “getNumericArray” by using the following technique:
- First we’ll initialize a new array with the desired length using an array constructor.
- We’ll fill this array with temporary values, since the array is still empty.
- We’ll use the map method to iterate through the array. We’ll use the second parameter in the function that map takes the current item’s index and populate the array with the desired variables. Learn more about map here.
Notice how we’ve transformed an array using the dot notation, since all three lines produce arrays.
Sure, we could have written something like:
But there’s no need to. It’s just more code and overhead. Sure enough this was the first thing in JS I personally found odd and unintuitive. But like many other things I have grown accustomed to it and now feel much more comfortable with.
Now it’s time to transform our main function from a loop to a map.
I had to change result from const to let because it is reassigned. But hold on! We just learned that we can use the dot notation to mutate an array without re-assigning. So let’s do that.
We’re nearly there. Let’s also change the cumbersome if-else statements with the ternary operator. Learn more about the ternary operator here. This way we don’t even need the brackets, since there’s just a long conditional return value.
And since zero stands for a boolean false, we can shorten this even further like so:
And in case you were wondering, yet we could have folded the entire algorithm into a single line:
But hey, wasn’t the original task about outputting strings and not arrays?
Sure, why not.
Take a look at the original solution vs this one and see what a distance we’ve covered. That only goes to show that you should never get stuck with only a single notion on how to deal with a coding challenge (or other real life challenges for the matter).
And here’s a challenge for you. Can you come up with a solution to a completely generic FizzBuzz-like challenge? i.e.:
- The function will generate a consecutive list of numbers. Dynamic start to end.
- It will accept any number of rules which will represent a divisor and a string with which it will replace the corresponding numeric value.