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?
What are higher-order functions?
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.
As a big fan of functional programming, I love higher-order functions. They are useful for writing more readable and easier-to-maintain code. And its a paradigm I often use when working with JavaScript/TypeScript, especially when working with React. Though I gotta admit, I haven't used that much of it when working with Python.
Higher-order functions are great, but...
Why would I use higher-order functions?
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 filter
, map
, forEach
methods in JavaScript? Those are excellent examples of higher-order JavaScript functions.
Writing your first higher-order functions
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.
All code samples are provided in Python and JavaScript as those are the language I'm most familiar with, but if you want to help, you can send me these same functions in other programming languages, and I'll gladly add them here.
Taking a function as an argument
To start, let’s build a very simple function, doOperation
which takes 3 arguments:
- The function operation
- number1
- number2
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.
Python:
def doOperation(operation, number1, number2):
return operation(number1, number2)
def sumBothNumbers(number1, number2):
return number1 + number2
doOperation(sumBothNumbers, 3, 5)
------------
Output
------------
8
Javascript:
function doOperation(operation, number1, number2) {
return operation(number1, number2)
}
function sumBothNumbers(number1, number2) {
return number1 + number2
}
doOperation(sumBothNumbers, 3, 5)
------------
Output
------------
8
Returning a function
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.
Python:
def multiplyBy(multiplier):
def result(num):
return num * multiplier
return result
multiplyByThree = multiplyBy(3)
multiplyByThree(4)
------------
Output
------------
12
JavaScript:
function multiplyBy(multiplier) {
return function result(num) {
return num * multiplier
}
}
multiplyByThree = multiplyBy(3)
multiplyByThree(4)
------------
Output
------------
12
Building Filter(), Map() and Reduce()
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.
filter() aka filtering()
The 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.
Python:
def filtering(arr, test):
passed = []
for element in arr:
if (test(element)):
passed.append(element)
return passed
def isSuperNumber(num):
return num >= 10
filtering([1, 5, 11, 3, 22], isSuperNumber)
------------
Output
------------
[11, 22]
JavaScript:
function filtering(arr, test) {
const passed = []
for (let element of arr) {
if (test(element)) {
passed.push(element)
}
}
return passed
}
function isSuperNumber(num) {
return num >= 10
}
filtering([1, 5, 11, 3, 22], isSuperNumber)
------------
Output
------------
> (2) [11, 22]
map() aka mapping()
The function 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.
Python:
def mapping(arr, transform):
mapped = []
for element in arr:
mapped.append(transform(element))
return mapped
def addTwo(num):
return num+2
mapping([1, 2, 3], addTwo)
------------
Output
------------
[3, 4, 5]
JavaScript:
function mapping(arr, transform) {
const mapped = []
for (let element of arr) {
mapped.push(transform(element))
}
return mapped
}
function addTwo(num) {
return num + 2
}
mapping([1, 2, 3], addTwo)
------------
Output
------------
> (3) [3, 4, 5]
reduce() aka reducing()
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.
Python:
def reducing(reducer, initial, arr):
acc = initial
for element in arr:
acc = reducer(acc, element)
return acc
def accum(acc, curr):
return acc + curr
reducing(accum, 0, [1, 2, 3])
------------
Output
------------
6
JavaScript:
function reducing(reducer, initial, arr) {
let acc = initial
for (element of arr) {
acc = reducer(acc, element)
}
return acc
}
function accum(acc, curr) {
return acc + curr
}
reducing(accum, 0, [1, 2, 3])
------------
Output
------------
6
FAQs
Why are they called higher-order functions?
A higher-order function takes its name because they typically act on or return functions from a higher order (or level) of abstraction.
What is functional programming?
Functional programming is a programming paradigm focusing on writing programs as a series of functions rather than code with a mutable state. It emphasizes using higher-order functions and immutable data structures to create modular, maintainable code.
Are higher-order functions a common topic in interviews?
Yes, higher-order functions are a common topic in software engineering interviews, it depends on the programming role and language, but generally speaking, it is good to know it. They are an important aspect of functional programming and writing code with scalability and reusability in mind. Knowing how to write and use higher-order functions is essential for software engineers who want to work on modern web or mobile applications.
Conclusion
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!
Newsletter
Subscribe to my weekly newsletter for developers and builders and get a weekly email with relevant content.
Top comments (0)