Marius Schulz
Marius Schulz
Front End Engineer

Passing Swift's Operator Functions to Higher-Order Functions

I've already talked about operator functions in my previous two posts:

In Swift, operator functions are used to provide an implementation for an operator. They're normal functions and can therefore be used as such, for example as a parameter to a higher-order function like reduce. Let's see how we can put that to use.

#Summing Up an Array of Numbers Using reduce

Assume you're given the following array of numbers:

let numbers = [2, 3, 5, 7]

How would you calculate the sum of all values in the array? Coming from a procedural background, you might iterate over the array using a for-loop and add each number to a local variable:

var sum = 0

for number in numbers {
    sum += number
}

// sum is 17

However, you can also choose a more functional approach and utilize the reduce function with an initial value of 0 to which every number is added, step by step. Its combining function should receive the accumulated sum (up to that point) and the current value, add them together and return them.

The combining function should therefore have an (Int, Int) -> Int signature. As it just so happens, the existing + operator function fulfills this criterion perfectly. We can plug it right into reduce:

let sum = numbers.reduce(0, +)
// 17

#Passing Binary Operator Functions to reduce

Let's now look at some other binary operator functions that we can pass as a combining function to reduce. How about * for multiplication? This time, we'll pass 1 as the initial value:

let product = numbers.reduce(1, *)

You're not restricted to just arithmetic operations, though. The + operator can, for example, also be used to concatenate arrays. The initial value is an empty array in this case:

let primeSets = [[2, 3, 5], [7, 11], [13], []]
let combinedSets = primeSets.reduce([], +)
// [2, 3, 5, 7, 11, 13]

#Passing Unary Operator Functions to map

While reduce works nicely with binary operator functions, map requires a transformation function accepting a single parameter. That's exactly what unary operator functions can be used for. Here's how to quickly negate every value in an array of numbers using -, the unary minus operator:

let primes = [2, 3, 5, 7, 11, 13]
let negatedPrimes = primes.map(-)
// [-2, -3, -5, -7, -11, -13]

A similar effect can be achieved for arrays containing Boolean values. The logical NOT operator ! will return the inverse value for each item in the array:

let logicalValues = [true, false, true]
let invertedValues = logicalValues.map(!)
// [false, true, false]

If you have other use cases where you pass operator functions to higher-order functions, please share them in the comments below!