Practical Functional JavaScript — Step 2: Higher-Order Functions

Kumar Bhot
webf
Published in
4 min readDec 4, 2018

--

This is the 2nd article of the series Practical Functional JavaScript.
[ Previous | Next ].

Working with higher-order functions

Immutability and Pure functions are the primary building blocks of Functional Programming. The second logical step is to make the data transformation visible. With imperative constructs, it is almost impossible to see what exactly is happening with the data. for-loops are the masters in stealing this transparency. In JavaScript, it is possible to handle almost every logic that can be built with for-loops using functions that accept functions as arguments — thereby adding complete clarity to data transformation.

The fact that we can pass a function as an argument to another function, it allows us to compose multiple functions into a bigger function a.k.a. Higher-Order Function.

A function is higher-order if it either takes a function as an argument or returns a function as a result; or does both

If you recall the illustration of Pure Function from our first article (Step 1), we can extend that block to represent a real scenario where a function invokes other functions to achieve its own results.

An application is nothing but a combination of multiple such functions. In general, what an application does is pass data from one function to another function (imagine data flowing through a pipe) where some of its functions might be internally invoking other functions and even taking function itself as an input or resulting a function as an output. It is also possible that a part of the pipe is being executed multiple times — recursion. Similarly over a period of time, the application may receive multiple inputs. We can visualize these multiple values as a list — which in JavaScript is represented as an Array.

Data as a list of values being transformed through a pipeline of functions

“Simplicity is the key to reliability.” — Dijkstra

The simplest system is the one where you can visualize the input value being transformed into an output by passing it through a series of smaller transformations.

This is the promise of Functional Programming!

To reason or think about an application as a series of data transformations we need to start taking baby steps in that direction. The best way to start is with Arrays because it has three power methods map(), reduce() and filter() that help us see the input being transformed through a pipeline of functions.

Map()

You are trying to convert one list into another form of a list, keeping the number of records intact.

Example: List of numbers to list of square of those numbers

[1, 2, 3, 4, 5].map(a => a * a); // will produce [1, 4, 9, 16, 25]

Reduce()

You are processing all the values from a list into a single value.

Example: List of numbers to sum of those numbers

[1, 2, 3, 4, 5].reduce((a,b) => a + b); // will produce 15

Filter()

You are extracting out values from a list into another (shorter) list based on some criteria for individual values in the original list.

Example: List of numbers to list of only even numbers

[1, 2, 3, 4, 5].filter(a => a % 2 === 0); // will produce [2, 4]

Most of the processing needs can be handled with the help of just these three tools. All that’s needed is practicing to do so.

Some quick examples:

From the record of sales, choose the sales of ‘Dave Noah’ from the month of November to display. Also display the aggregate sales amount for the chosen records.

That was a no-brainer. Let’s take a little complex requirement. There is a list of staff in an office. The HR person is asked to submit the list of vehicles owned by all their staff members to the Parking Manager. The HR person simply needs a flat list of vehicle numbers; no other information is needed.

The first thing we see with applying these higher-order functions in the above solution is the beauty that it brings to the code flow. It is concise and explicit. In an otherwise imperative approach, we’ll need a blank array to start with which will be pushed with the plate numbers in an inner forEach, iterating over cars inside an outer forEach to iterate over staff members. The above code does the exact same thing but in a pure functional manner => Immutability + Higher-order Functions.

The use of reduce() is likely to be the trick and heart of the solution. We need to get into a practice like this and tweak the solution to apply the combination of map/filter/reduce. Doors to the world of Function Programming open by thinking Immutability.

Takeaway

  1. If your data structure isn’t a List, try to convert that into a List; so that the map/reduce/filter power can be applied to your solution
  2. Stop using for(), for-in() or forEach(); they all eventually lead to mutations. Step 1 always comes first — Think Immutability and Pure Functions. Some Array() methods modify the original state (in place algorithm) e.g. splice(), push() etc.; stay away. Utilize Array() methods that return a new instance of an Array() e.g. concat(), slice() etc.
  3. Tweak your solution around map()/filter()/reduce()

Practice this for a few days before moving on to the next step.

Explore more

--

--