# Equatable

## Adventures in Swift value equality.

31 July 2018 ∙ Protocols ∙ written by

Equality and the `Equatable` protocol in Swift are all about value equality.

In our world of value types, if `a = 5` and `b = 5` then `a` and `b` are the same. Any place you pass in `a`, you could just as well pass in `b` and not notice any difference.

In other words, `a == b`.

Reference types can also have equal values but add the additional question of identity and the identity-of operator `===` (triple equals) into the mix. We’ll only consider value equality for this article.

What are the requirements of the `Equatable` protocol?

## Equatable Protocol

If your type conforms to `Equatable`, you can compare two values of the type with `==` and `!=`.

The protocol has a single requirement: the `==` function:

``````public protocol Equatable {
static func == (lhs: Self, rhs: Self) -> Bool
}
``````

It takes two values, and returns a `Bool` saying whether they’re equal.

Thanks to a protocol extension, you don’t need to provide `!=` as there’s a default implementation:

``````public static func != (lhs: Self, rhs: Self) -> Bool {
return !(lhs == rhs)
}
``````

If we wanted to screw it up, we could return a random `Bool` value each time for inconsistent results. We probably have some intuition that this would be bad, but what are the official invariants we should keep in mind?

According to the documentation, equality comparison results should have these three properties:

• Reflexive: a value always equals itself; `a == a` must always be `true`.
• Symmetric: the order of the values doesn’t matter; `a == b` means `b == a`.
• Transitive: value relationships chain together; if `a == b` and `b == c` then `a == c`.

That covers the protocol requirements. How do we implement it for our own types?

## Implementing Equatable

Back in the old days, you had to write oftentimes tedious code for `==`:

``````func == (lhs: Dog, rhs: Dog) -> Bool {
return lhs.name == rhs.name &&
lhs.breed = rhs.breed &&
lhs.age == rhs.age &&
lhs.size == rhs.size &&
// ... etc. 😓
}
``````

Even worse were enumerations with associated values: you had to have a switch, check for each case, bind the values, and then do the `==` dance for each one.

### Auto-Equatable

As of Swift 4.1, the compiler can generate the `==` function for you in some cases.

Given this example struct:

``````struct Puppy: Equatable {
let name: String
let age: Int
}
``````

The compiler will be able to write `==` since both properties, `String` and `Int` themselves conform to `Equatable`.

## Conditions for Conformance

What are the requirements to not have to write `==` yourself?

For classes, you’re out of luck; there’s no synthesized conformance and you always have to do it yourself. 😓

For structs, all stored properties must conform to `Equatable`. If the struct has no stored properties, then its instances will all equal each other (i.e. `==` will always return `true`).

For enumerations, it depends on the associated values.

• If there are no associated values and just bare cases, then you can get `Equatable` conformance.
• If there are associated values, then all of their types must conform to `Equatable`.

There’s one extra edge case: as of Swift 4.1, an enumeration with no cases will not get synthesized conformance (although this will change in a future version of Swift).

Of course you can always add your own `==` implementation, and then the compiler won’t bother to auto-generate one for you.

## The Closing Brace

`Equatable` is a simple protocol and is even easier to work with thanks to automatic conformance in Swift 4.1.

If you’re curious how the compiler does the work to synthesize an implementation, you’re in luck! Check out the article Synthesized Conformance to Equatable for the details.

If you want more protocols, four other protocols build on top of `Equatable`:

Learn about one protocol, and more spring up. Turns out it’s protocols all the way down. 🐢

`}`