Introduction to Higher-Order Functions

Understanding higher-order functions like map, filter, and reduce with examples

Devin Soni
Oct 7 · 4 min read
Photo by Safar Safarov on Unsplash

Higher-Order Functions

A higher-order function is a function that accepts another function as a parameter or returns a function as its return type. The easiest way to understand this is by realizing that functions can be treated just like any other piece of data.

In languages that support higher-order functions, much like you would with a String or Integer, you can pass functions as parameters, store them, and return them.


Anonymous Functions

Before exploring higher-order functions, it is first important to cover anonymous functions, which are often used alongside higher-order functions.

An anonymous function, or lambda, is simply a function that was declared without any named identifier to refer to it. They can still be stored in variables and therefore can still be named within the code, but the function itself is declared without a name attached.

For example, in Java, a simple anonymous function looks like this:

x -> x + 1

The input of this function is x, and the output is x + 1.

Syntax for anonymous functions varies slightly across languages, but it is typically written in the form of (inputs) → (output).

Anonymous functions are often used because they avoid the boilerplate code associated with formally declaring them as named functions. So, for simple functions that may not be used in more than one place, such as the above, it may be more appropriate to use an anonymous function.

Now, we will go into a very basic example of a higher-order function that uses anonymous functions. This example uses Python, where the syntax for anonymous functions is lambda (inputs): (output).

def add_n(n):
return lambda x: x + n

This example takes a number n and returns a function that adds n to the input.

So, if we wanted to add 1 + 2, we could do that by calling add_n(2)(1). The first call, add_n(2), returns a function that adds 2 to its input, and the second call (1) uses that function to add 2 to 1.


Common Higher-Order Functions

There are a few specific higher-order functions that are essential to understanding modern codebases. These primarily deal with iterating or summing up lists of data.

They provide a much cleaner way to deal with common list operations, saving you from having to create a lot of helper code to do basic list operations. This creates code that is more explicit in its intention.

For these examples, I will use Python-ish code throughout. Most other modern languages, such as Java and JavaScript, also have these features.

The map operation allows you to apply a function to each element of a list, and then return a new list with those new values.

Without map, your code to do this would look like this:

new_list = []
old_list = [...]
for e in old_list:
new_list.append(some_function(e))
return new_list

Here, our goal was to apply some_function to every element of old_list. At the end of this loop, new_list now contains this result.

With map, we can do this in a much cleaner way.

The map function takes in a function and a list, and returns a new list with that function applied to every element of the list. It is used as follows:

old_list = [...]
return map(some_function, old_list)

So, if old_list = [1, 2, 3] and some_function = lambda x: x + 1 , the returned value would be [2, 3, 4] .

The filter operation allows you to return the elements of a list that meet a condition.

Without filter, your code to accomplish this would look like this:

new_list = []
old_list = [...]
for e in old_list:
if some_function(e):
new_list.append(e)
return new_list

Here, we want to return the subset of elements in old_list for which some_function returns True.

With filter, we can, again, do this in a much cleaner way. Filter takes in a function and a list, and returns a new list with only the elements in that list for which the function returns True.

We use filter as follows:

old_list = [...]
return filter(some_function, old_list)

So, if old_list = [1, 2, 3] and some_function = lambda x: x == 2 , then the return value of this would be [2] .

The reduce operation allows you to calculate a single value based on a function used to combine all of the elements of the list. For example, this could be adding all of the elements of a list to find the list’s sum.

Without reduce, your code would look like this:

accumulator = 0
old_list = [...]
for e in old_list:
accumulator += e
return accumulator

The accumulator variable is initialized with a value (0, in this case), and holds the accumulated result of applying a function to the accumulator and each list element.

In this case, the function is lambda accumulator, e: accumulator + e.

So, for a given function f, the reduce operation is equivalent to calling f(...(f(f(initial, list[0]), list[1]),...), list[n]).

For example, say old_list = [1, 2, 3, 4] and we use the function lambda accumulator, e: accumulator + e with an initial value of 0.

Then, the value of our reduce operation would be ((((0 + 1) + 2) + 3) + 4), which is exactly the same result as the snippet above.

We can use reduce as follows:

old_list = [...]
initial = 0
return reduce(lambda acc, e: acc + e, old_list, initial)

(Note that Python’s actual reduce function does not take an initial value as a parameter — it just uses the first value of the list as the initial value. The above syntax is more generalized to what other languages do.)

Better Programming

Advice for programmers.

Devin Soni

Written by

Software Engineering / Machine Learning

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade