Like many of you, I’ve only really heard of functional programming over the last number of months. Initially I looked at some functional examples and thought:
“This is seriously f**ked up…”
Then I read some articles on how writing you code more “functionally” and it made sense to me. For example, writing “pure” functions that don’t have any side effects means you don’t have to worry about functions returning the wrong value if they’re called twice. And writing functions that all return values, means you can chain them together, making your program both more concise and expressive.
Before we continue any further I want to lay some ground rules that I personally found useful for writing my code more functionally.
- Write a functions that do one simple thing
- Have each function return values and take a parameters.
- Treat variables as immutable values
- Forget about
for(var i = 0;i<...)loops, use
forEachand the various functions built on top it
Functional programming requires you to write “pure” functions which basically means no matter how many times you call it, provided the parameters don’t change, it will return the same value. The classic example is this:
If we the impure add several times multiple times we get a different answer each time. When dealing with complex programs or programs with multiple threads, it’s comforting to know that if a function is called multiple times it will always return the same answer.
In this example we’re going to take some weather data from openweathermap and make a new object like so:
The data below is the 7 day forecast for the city of London. We’re going to start with something basic like calculating the average temperature of the 16 day period. The sample data can be found here.
Get the average temperature
Right, the first thing we want todo is loop through the list of days and extract the temperatures for each day and store them in a new array. We could do it this way:
This is the easiest way to get the values, but it quite frankly sucks. We could write the same code as follows:
We managed to reduce 4 lines of code to 1 neat one. There are 3 things we’ve done:
Made temperatures a constant variable, it can no longer be changed
mapfunction which along with
for eachloop and most importantly allow us to pass a function as a parameter.
Now, let’s find the average temperature. To do this we’re going to use the
reduce function. The
reduce function takes an array and reduces it to a single element. Below we’re going to get the sum of the array of temperatures and divide it by the number elements in the temperatures array.
It’s relatively straight forward. However, we could make the code more concise as follows:
Congrats!!! In what would’ve taken multiple lines of code to do we managed to do it in two lines or even just one. A problem you can see with the above snippet is that as you start chaining functions together it comes at the cost of readability.
Get the average rainfall
We’re going to do what we did in the last example except we’re just interested in the rainfall. Since, it doesn’t rain everyday we’re going to
filter out the non-rainy days from our data and calculate the average rainfall.
So first things first we’re going to filter our array by doing the following:
It’s nothing spectacularly different. The key thing here is to note that the callback function must return a
boolean. Note that there was an error with the data where on 1 day it was raining but there was no rainfall data 😕.
Now we repeat the same steps as we did with the average temperature.
This function is fairly self explanatory. Execpt we use the index of the array we’re mapping through to pair up both arrays. Also, note that if one array is longer than the other we discard the remaining elements. In languages that use lazy loading like Haskell it’s possible to zip an infinite array with a finite array.
Now using this zip function we can do the following:
Finally we can use what we’ve learnt to create this structure by wrapping up our functions into another function that returns the needed structure:
What’s interesting about writing pure functions is that you break problems into to simple tasks. Which more often than not could be done in parallel. For example, say you were tasked with getting the information above, but for all the cities in the world. You could easily use the above the functions and techniques in a mapreduce model and designate N nodes to calculate the average temperature, etc.
If you made it this far thanks for reading this post and hopefully you might have found it useful.😊