Swift: Equatable with Optionals
@andrewcbancroft recently wrote a great article about how Every Swift Value Type Should Be Equatable – go ahead and read it, I’ll wait…
One thing that stood out as missing from this article was comparing different sets of optional values. In the past, I have implemented the following equality for values to make sure optionals were covered:
1 2 3 4 5 6 7 8 9 10 |
// comparing two non-optionals func ==(lhs: Place, rhs: Place) -> Bool { /* your implementation here */ } // comparing one optional / one non-optional value func ==(lhs: Place?, rhs: Place) -> Bool { /* your implementation here */ } func ==(lhs: Place, rhs: Place?) -> Bool { /* your implementation here */ } // comparing both optionals func ==(lhs: Place?, rhs: Place?) -> Bool { /* your implementation here */ } |
I mentioned this in my Swift Newsletter this week, only to get the following responses on Twitter:
@NatashaTheRobot Re: Equatable, you should be able to skip the last one at least since Swift defines it.
— Rob Rix (@rob_rix) July 6, 2015
@NatashaTheRobot @rob_rix and, unless something changed, you can skip the other two as well because of implicit conversion to optional
— anatomisation (@anatomisation) July 6, 2015
Of course, I had to see it for myself, so I tried this in the playground:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
struct Place { let name: String let latitude: Double let longitude: Double } extension Place: Equatable {} func ==(lhs: Place, rhs: Place) -> Bool { let areEqual = lhs.name == rhs.name && lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude return areEqual } let sf = Place(name: "San Francisco", latitude: 37.7833, longitude: 122.4167) let sfOptional: Place? = Place(name: "San Francisco", latitude: 37.7833, longitude: 122.4167) let sfOptional2: Place? = Place(name: "San Francisco", latitude: 37.7833, longitude: 122.4167) let ny: Place? = Place(name: "New York", latitude: 40.7127, longitude: 74.0059) let noPlace: Place? = nil let noPlace2: Place? = nil sf == sfOptional // true sfOptional == sfOptional2 // true sf == sfOptional2 // true sfOptional2 == sf // true sf == ny // false ny == sfOptional2 // false noPlace == noPlace2 // true sfOptional == noPlace // false |
Turns out, the Equatable implementation for optionals is not necessary. It just works!