When we think of functions in any programming language, we think of reusable code abstracted into a separate block that performs specific tasks. Such functions can take inputs, process them and provide output according to the instructions coded in the function.
Functions normally receive values as inputs, such as numbers, strings, and references or copies of objects and lists, and would optionally return values in those types.
But hold on, what if, for example, we are implementing a
timer function that, after X seconds passed, will execute a given piece of code? Could such a
timer function have another function as its input?
In computer science, higher-order functions (a key element of functional programming) are functions that can take other functions as inputs or return them as outputs. They, therefore, allow us to create abstractions over existing functionality and compose new functionality out of existing ones.
Higher-order functions are great, but…
Higher-order functions are useful for writing code that is more general, extensible, and reusable. You can use them to create abstractions over existing functionality and compose new functionality out of existing ones. Additionally, they let you control scope, simplify callbacks (like promises), eliminate unnecessary code duplication, and write cleaner code by separating the logical flow from the implementation details.
Ever worked with
Let’s start simply by building two different higher-order functions. The first one would take a function as input, while the second example would return a function. Next, we’ll write our own definitions for some of the most popular higher-order functions, some of which we have already named before.
To start, let’s build a very simple function,
doOperation which takes 3 arguments:
- The function operation
Additionally, we will create an operation called sumBothNumbers which will simply return the sum of 2 numbers.
The idea is that
doOperation would run the given operation function to both numbers and return the final result. The
operation input can by any function that takes two numbers and performs a calculation, such as calculating the sum of both numbers.
Next, we will build a higher-order function that returns a function. Our function will be called multiplyBy and it will take a number as an argument and return a function that will multiply its input by that number.
We are getting pros at working with higher-order functions, and though it may still take some practice to find out good opportunities to use them, you are in great shape to work on some more complex implementations.
To level up our higher-order functions skills, we will write the code for some of the most popular array methods in the functional programming paradigm.
filtering function will have 2 parameters, an
array and a
test function. It will return a new array with all the elements that pass the test.
mapping will take 2 parameters: an
array and a
transform function, and it will return a new transformed array where each item is the result of the
transform function called over each element of the original array.
The function reducing will take 3 parameters: a reducer function, an initial value for the accumulator and an array. For each item in the array, the reducer function is called, passing it to the accumulator and the current array element. The return value is assigned to the accumulator. After reducing all the items in the list, the accumulated value is returned.
Next time when you get to that interview, or simply you see a pattern where a function is either returned or taken as a parameter, you will know we are dealing with higher-order functions.
Today for the first time, I’ve introduced an article covering more than one language. If you find it a great way to showcase and compare them, or if you think it was a terrible idea, please let me know in the comments or by Twitter. I’d love to hear your ideas.
Thanks so much for reading!