Custom Operators in Swift with Generics

Custom Operators in Swift with Generics

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.


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

Update - Included Generics example

One of my colleagues mentioned that he came across this blog post and he loved it. I am delighted to hear it. However, I also realized that I don't have any example to demonstrate generics. I am planning to fix it in this update.

For this example, we will extend the code listed above with ^^ operator.
We will make first parameter numeric generic so that we can pass it as a number of any type (Double, Float, Int) and we still fix second parameter as Int since this is going to be power. Examples with updates generic code is as follows

infix operator ^^

public func ^^ <T: Numeric>( value: inout T, power: Int) {
    var finalValue: T = 1
    for _ in 0..<power {
        finalValue = finalValue * value
    value = finalValue

Now, given this code we can calculate power of any Swift Numeric type including following types

  1. Float
  2. Double
  3. Int
  4. Binary
  5. Octal
  6. Hexadecimal

Please note however that we still want to keep power as Int since that is the requirement. You can still change the base to any Numeric type given the constraint we imposed on custom type.

var floatValue: Float = 89.45
var doubleValue: Double = 10.45
var intValue: Int = 100
var binaryValue = 0b100
var octalValue = 0o11
var hexadecimalValue = 0xFA

let expectedPower = 3

// floatValue = 715716.438
floatValue ^^ expectedPower

// doubleValue = 1141.1661249999997
doubleValue ^^ expectedPower

// intValue = 1000000
intValue ^^ expectedPower

// binaryValue = 64
binaryValue ^^ expectedPower

// octalValue = 729
octalValue ^^ expectedPower

// hexadecimalValue = 15625000
hexadecimalValue ^^ expectedPowercale

This is all for this update. Given the history of my several updates, I will try not to update this post anymore or if necessary will try to make a new one. Hope this helps. This post can now be called as a Custom operators in Swift with Generics. Thanks a lot for reading!


Facets of Swift, Part 5: Custom Operators

Custom Operators in Swift

Podcast by Erica Sadun