DEV Community

Brett Martin
Brett Martin

Posted on • Updated on

Higher Order Functions & Functional Composition

Originally published @ CatStache.io

Have you ever wondered what a Higher Order Function (HOF) is, and how it might help you when writing code? Well look no further!

In this post I will show some examples of where HOFs are used in daily JavaScript, how you can write your own, and as a bonus a small section on composing functions.

What are Higher Order Functions (HOF)?

Simply put, a higher order function is a function that does either, or both of the following:

  1. Take one or more functions as arguments.
  2. Returns a function.

Here is a simple example of some code that you may write that makes use of a HOF:

const nums = [1,2,3,4,5,6];

const isEven = number => {
  return number % 2 === 0;
};

// evens will be an array with elements [2,4,6]
const evens = nums.filter(isEven);
Enter fullscreen mode Exit fullscreen mode

Here we make use of the array filter method which takes as an argument a function that takes a single argument (an element of the array) and returns true if the element should be kept, and false if the element should be discarded.

You might also find the above code written with an anonymous function instead, which would look something like this:

const nums = [1,2,3,4,5,6];
const evens = nums.filter(n => n % 2 === 0);
Enter fullscreen mode Exit fullscreen mode

While the above code demonstrates filter, you will find many examples of passing in functions as arguments to other methods for arrays such as map, reduce, every, etc. This pattern will start to pop up all over the place in JavaScript code - you probably were already making use of this concept without knowing its name!

Extending our isEven function

One thing that is nice about HOFs is that they allow use to write some code to combine functions in new and interesting ways. Imagine our code from above is growing and we need to also be able to get a list of odd numbers. We could easily write an isOdd function that would be very similar to isEven, but we also know that in this case it would just be the exact opposite of isEven. Unfortunately we can't just write const evens = nums.filter(!isEven), even though that is basically what we want. What we can do is create a new function called not that takes a function as an argument, and returns a new function that will invert the value of the passed in function:

const nums = [1,2,3,4,5,6];

const isEven = n => {
  return n % 2 === 0;
};

const not = f => {
  return x => !f(x);
};

const isOdd = not(isEven);

// odds will be an array with elements [1,3,5]
const odds = nums.filter(isOdd);
Enter fullscreen mode Exit fullscreen mode

Awesome! Our function not satisfies both requirements for being a HOF because it takes a function as an argument and it returns a new function as its result, which we bind to isOdd. You can make use of HOFs to build more complex functionality by reusing logic of smaller functions, sweet!

Cleaner Code With Function Composition

While function composition isn't strictly related to the topic of HOF, it is something you may want to use for writing clean functional code. I would suggest you reach for a library such as lodash/fp or ramdajs to grab their compose function. Here is the documentation for ramdajs's compose.

While writing not as a HOF, I did add some extra machinery by taking a function and returning a function to work in my example. The simplest, standalone version of not would be written as const not = v => !v;. That is, it just takes a boolean value and returns the inverse. I can write the not function this way if I make use of compose. Here is an example of doing just that:

import R from 'ramda';

const nums = [1,2,3,4,5,6];

const isEven = n => n % 2 === 0;
const not = v => !v;
const isOdd = R.compose(not, isEven);

const odds = nums.filter(isOdd);
Enter fullscreen mode Exit fullscreen mode

In my opinion, this is the cleanest version of the code so far, and the best part is R.compose takes as many functions as necessary! This allows us to start writing functional code that is composable and easy to test and reason about!

Conclusion

In the end, Higher Order Functions are prevalent in JavaScript - if you stumbled across this while trying to learn there is a chance you were already making use of this concept without knowing it! If you end up leaning towards writing more functional JavaScript, HOFs will be a concept you make use of heavily, and when paired with composition the code will become easy to test, combine, and reason about!

Discussion (3)

Collapse
lukeshiru profile image
LUKESHIRU

You could even use currying like this:

const multipleOf = multiple => number => number % multiple === 0;
const isEven = multipleOf(2);
Enter fullscreen mode Exit fullscreen mode

Nice to see this kind of functional coding in JS in DEV.

Cheers!

Collapse
bamartindev profile image
Brett Martin Author

Absolutely! I love to curry when I can, and I feel like es6 made it so much easier to curry. I think that might be a good topic to write about in the future 😀

Collapse
parenttobias profile image
Toby Parent • Edited on

In all the array HOF methods, composition is a very powerful construct. A filter method for isInRange, the ability to sort arrays of objects by multiple keys... Fun stuff!

Been doing a similar series on freecodecamp's need feed about this same subject. It's one near and dear to my heart. Thank you for a thoughtful and approachable look at composition.