Functional Programming and Function Chaining in JavaScript

function-js

Functional Programming is a declarative programming paradigm that has existed for a long time and the internet is full of articles trying to depict it as OOPs powerful counterpart. It only takes you to search functional vs OOP to see the raging opinion war.

Functional programming is when functions, not objects or procedures that are the fundamental building blocks of a program.

Over the past few days I decided to dig deeper into functional programming and I am writing a series of articles simply to document my learning and in the hope that it will guide the next JavaScript developer treading these lands.

I already have exposure to functional concepts. Concepts like using map/reduce/filter, side effects, higher order functions, pure functions and state immutability. But I want to dig deeper into function composition, function currying, functors, monads e.t.c.

This article will take this structure:

  • Why functional programming
  • Key concepts/terms in functional programming
  • Examples of code from non-functional to functional

Why Functional Programming?

  1. Functional programming is declarative, in that it focuses more on what you need done as opposed to how. This gives you only one dimension to focus on. Languages like Java are imperative thus you have to focus on both dimensions.
  2. Functional code is less detailed and more readable. You will see how this comes to play in the examples that will follow.
  3. Functional code is easier to test. This is derived from it support of pure functions and immutability. Read on to understand what these terms mean.

Few key functional concepts/terms

  1. Pure functions

Pure functions are functions that:

  • The output is determined by the input. Given the same input it will have the same output.
  • Have no observable side effects.
  • Rely on no external mutable state.
// Pure function
const add = (a) => a + 10;
// Impure, depends on mutable data
let a = 5;
Const add = (a) => a + 10
  1. Immutability

Immutability means once data is defined, it cannot be mutated. This makes functional programming favorable as you can easily test it and means you do not expect any side effects. It also makes you reason about your code.

  1. Higher Order Functions

Higher Order Functions are functions that:

  • Receive functions as arguments
  • Return a function as a result

Code Examples:

An obvious trigger that you need to write functional code is when you encounter a for loop. In our example, let’s say you have an array of objects that contain user information:

let users = [{
  name: 'Gertrude',
  isEmployed: true,
  salary: 50
}, {
  name: 'Nyenyeshi',
  isEmployed: false,
  salary: 0
}, {
  name: 'Sheshe',
  isEmployed:true,
  salary: 100
}, {
  name: 'Gertrude',
  isEmployed: true,
  salary: 900
}];

From this data you are required to get all users named Gertrude and also get the sum of their salaries.

On the get go, if you do not have any experience with functional programming, you will do this:

let arr = [];
let sum = 0;

for (let i = 0; i < users.length; i++) {
  if (users[i].name === 'Gertrude') {
    arr.push(users[i]);
    sum += users[i].salary
  }
}

You will declare a new empty array then loop through the array and check for every object.name that matches Gertrude and push it into this array. You will also increment a variable sum with an initial value of 0 with the salary values to get the salary total.

This looks like a neat solution but let us explore the functional way. JavaScript arrays contain the method filter that creates a new array with the array elements that pass a particular test. Let us implement that:

let result = users.filter((a) => {
  return a.name === 'Gertrude'
});

Another method is the reduce method which reduces an array value into one single one. After filtering our array, we can then get the sum using the reduce method like this:

let result = d.reduce((acc, n) => {
  return acc + n.salary
}, 0);

Looking at our solution, it looks a little complicated than what we had before, but let’s keep going.

Function Chaining.

Because both filter and reduce return a new array, we can chain these two functions. Our solution now looks like this:

let results = users.filter((a) => {
  return a.name === 'Gertrude'
})
.reduce((acc, n) => {
  return acc + n.salary
}, 0);

We can now directly get the total salary of all users named Gertrude.

Our code already looks good but how about we make it a bit more readable:

const isGertrude = (a) => a.name === 'Gertrude';
const salarySum = (acc, n) => acc + n.salary ;

let result = users.filter(isGertrude)
.reduce(salarySum, 0)

Now we have a function that returns users named Gertrude, and one that gets the sum of their salaries.  At this point, when someone looks at your code, it definitely looks much more readable. They are able to quickly understand what is happening and not spend too much time on the how. That is the declarative power of functional programming.

You may also like

Leave a Reply

Your email address will not be published. Required fields are marked *