Introduction to Higher-Order Functions
By: Devin Soni
Tags: Software Engineering, Programming, Technology, Coding, Functional Programming

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.

Map

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] .

Filter

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] .

Reduce

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)