Custom Operators in Swift

Swift introduced us a new era of custom operators. Unlike Objective-C, it will allow us to define our own operators and perform operator overloading if necessary.
Although I haven't come across such use case, custom operators can provide excellent clarity and flexibility down the line. Let's start with how you can define custom operators in your application.

There are two ways operators can be used.

  1. Perform operation and assign a value to left hand side variable
    e.g. a = a + b

  2. Perform operation directly without having to make a manual assignment
    e.g. a += b

The second case is little bit tricky since in this case variable needs to be passed by a reference

Let's also go over three types of operators

  1. Prefix operator - Generally attached to the beginning of operand. Such as [operator][operand]. Also regarded as unary operator since it requires only one operand to work on.

  2. Postfix operator - Generally attached to the beginning of operand. Such as [operand][operator]. Also regarded as unary operator since it requires only one operand to work on.

  3. Infix operator - Generally attached between two operands. Also called a binary operator since it requires two operands to work on. e.g. [operand1][operator][operand2]

Prefix Operator

To start with custom operator, first you have to decide which special symbol to use for your operator. Let's choose a special character combination ++. This fictitious operator will increment value of operand by 2

We won't consider associativity and precedence for unary operators since they only apply for binary operators


// Operator definition
prefix operator ++

prefix func ++ (value: Int) -> Int {
    return value + 2
}

// Example
let value = 10
// result = 12
let result = ++value

Postfix Operator

Similarly we can define our postfix operator. The only difference being instead of prefixing operator we will postfix it


postfix operator ++

postfix func ++ (value: Int) -> Int {
    return value + 2
}

// Example
let value = 10
// result = 12
let result = value++

Infix Operator

This is an interesting part. Being an infix operator it involves more than one operands. We will also consume extra parameters such as precedence and associativity. Let's call our new operator ^^ which will compute 4th power of given number. Example, 2^2 evaluates to 4. 2^^2 will evaluate to 16.


// As per Swift 3.0 proposal you have to declare precedence group first before proceeding

// Here I have specified associativity right because I want this expression to be evaluated starting from right. For example, if it's x ^^ y ^^ z, it will be regarded as x ^^ (y ^^ z). 
// One more point to note, being a power operator, I am assigning it a precedence more than multiplication. So our double power operator will be evaluated first before applying any other operator

precedencegroup SuperPowerPrecedence {
    associativity: right
    higherThan: MultiplicationPrecedence
}

infix operator ^^: SuperPowerPrecedence

// Operator definition
public func ^^ (value1: Double, value2: Double) -> Double {
    return pow(pow(value1, value2), value2)
}

let value = 10
let power = 2

// result = 100000
let result = value ^^ power

Please note that in above example I have used a Swift 3.0 syntax. If you are making a transition from version 2.3, this example could be used as a good convertor to a new syntax.

There is one more way I promised to show you. How can you apply result directly without having to assign it to another variable. In short,
Instead of having to do
let result1 = 10 ^^ 2

You can instead do it like
value ^^ power // value = 10000


public func ^^ ( value1: inout Double, value2: Double) {
    value1 = pow(pow(value1, value2), value2)
}
// value = 10000
value ^^ power

However, the way you may want to use the infix operator really depends on your specific use-case. I can think of few use-cases where first case is useful, but there may be few cases where second use cases will be useful for readability.

Edit:

Recently I watched an amazing podcast by Erica Sadun on operators. So with that talk in mind, I would like to add one more example referring to custom operators.

Let's consider sets this time. Say, we want to add a custom operator to compute the intersection of two given sets.

Swift already provides a built-in function to compute this.

public func intersection(_ other: Set) -> Set

All we need to do is to make it succinct by using our custom operator. Being a math student, my obvious choice would be to use this (∩) classic intersection operator. Since this operator is going to operate on sets, let's add an extension on the type


infix operator ∩: SetOperatorPrecedence

precedencegroup SetOperatorPrecedence {
    associativity: left
    higherThan: MultiplicationPrecedence
}

extension Set {
    static func ∩(lhs: Set, rhs: Set) -> Set {
        return lhs.intersection(rhs)
    }
}

This should be it. So next time when you do,

let intersection = set1.intersection(set2)

This can easily be replaced with

let intersection = set1 ∩ set2

let set1: Set = [1, 2, 4, 6]
let set2: Set = [1, 20, 3, 6]

// Result = [6, 1]
let result = set1 ∩ set2

**References:**
[Facets of Swift, Part 5: Custom Operators](https://medium.com/swift-programming/facets-of-swift-part-5-custom-operators-1080bc78ccc#.vajsgfxew)
[Custom Operators in Swift](http://www.codingexplorer.com/custom-operators-swift/)
[Podcast by Erica Sadun](https://realm.io/news/slug-erica-sadun-operators-strong-opinions)

Jayesh Kawli

I am a web and mobile developer working at Wayfair in Boston, MA. I come to learn so many things during course of life and I write about things which helped me and feel like they can help others too.

Subscribe to Fresh Beginning

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!