Equality Operators in Swift: Double equal vs Tripe equal and how to define even your own Quadruple Equal operator

Yes, a quadruple operator. Bare with me, we’ll get there by the end of this post. In order to figure out how equivalence operators work, let’s start with a simple example:

Double equal

A double equal operator (aka ==) compares values. Let’s look at the simple example below:

5 == 5                             // => true
"same string" == "same string"     // => true
[1,2,3] == [1,2,3]                 // => true
"one string" == "different string" // => false

The left-hand side and the right-hand side are different objects in all three cases. Swift compares basic types with no problem. Let’s see how Swift is doing with our custom octocat classes:

class Octocat {
    var legs:Int
    var kind:String

    init(legs:Int, kind:String) {
        self.legs = legs
        self.kind = kind
    }
}

let eight_leg_octo = Octocat(
    legs:8, kind:"Coder")
let another_eight_leg_octo = Octocat(
    legs: 8, kind: "Coder")

// ERROR: Cannot invoke '==' with an argument list of type Octocat, Octocat
eight_leg_octo == another_eight_leg_octo

Error! Swift doesn’t know how to compare octocats. C’mon Swift! It’s not that hard, all you need is to compare the number of legs. Although it seems obvious for the author of this code, Swift doesn’t know how to compare custom objects. Every custom object has a meaning. It is pretty reasonable to push the responsibility of defining equivalence to the author. In order to do that, we need to define the equivalence operator for the Octocat class. All you need to do is to return true or false depending whether the left-hand side is equal to the right-hand side. Note that the equivalence operator is redefined outside of the class. But the Octocat type is specified inside parameters.

func ==(left:Octocat, right:Octocat) -> Bool {
    return left.legs == right.legs
}

Now Swift is all happy and our octocats are indeed equal.

Triple equal

The triple equal (aka ===) operator compares identity. If the variable on the left points to the same exact object that the variable on the right, then it returns true. It returns false otherwise. Here is the example:

class Skateboard {}
let red_skate = Skateboard()
let same_red_skate = red_skate

red_skate === same_red_skate // => true

let blue_skate = Skateboard()
red_skate === blue_skate     // => false

The red_skate variable and the same_red_skate variable point to the same exact instance of the Skateboard class. That’s why our tripe equal operator returns us true. The variable blue_skate on the other hand points to a different instance than what the red_skate variable points to. Therefore, the triple equal operator returns us false in the second case.

Custom operators

But wait, but there is more. Just to make things more fun, let’s introduce a quadruple equal operator for our Octocat class. Why not? It turns out that you can introduce pretty much any custom operator in Swift pretty easily. It’s a two step process. First, you’ll need to define a new operator. Be careful, it defines this new operator globally:

infix operator ==== {}

Then, you’ll need to implement it. Our quadruple equal operator makes absolutely sure that Octocats are the same. It compares the number of legs and the kind or an Octocat :-)

func ====(left:Octocat, right:Octocat) -> Bool {
    return left.legs == right.legs
        && left.kind == right.kind
}

Now that we have it, let’s use it:

eight_leg_octo ==== another_eight_leg_octo // => true

Recap

Swift has two major mechanisms for comparing objects. The equality operator and the identity operator. The equality operator compares values. The identity operator checks whether variables point to the same instance. Swift provides us with a way of defining custom operators. I can see it being useful in certain cases but you can easily take it too far. Before defining a new custom operator, ask yourself whether you can accomplish the same goal with existing operators.

Cheers,

Alex

Photo by ssoosay