I was thinking about how Swift ensures uniqueness for Set because I have turned one of my obj from Equatable
to Hashable
for free and so I came up with this simple Playground
struct SimpleStruct: Hashable {
let string: String
let number: Int
static func == (lhs: SimpleStruct, rhs: SimpleStruct) -> Bool {
let areEqual = lhs.string == rhs.string
print(lhs, rhs, areEqual)
return areEqual
}
}
var set = Set<SimpleStruct>()
let first = SimpleStruct(string: "a", number: 2)
set.insert(first)
So my first question was:
Will the static func ==
method be called anytime I insert a new obj inside the set?
My question comes from this thought:
For Equatable
obj, in order to make this decision, the only way to ensure two obj are the same is to ask the result of static func ==
.
For Hashable
obj, a faster way is to compare hashValue
s... but, like in my case, the default implementation will use both string
and number
, in contrast with ==
logic.
So, in order to test how Set
behaves, I have just added a print statement.
I have figured out that sometimes I got the print statement, sometimes no. Like sometimes hashValue
isn't enough in order to make this decision ... So the method hasn't been called every time.
Weird...
So I've tried to add two objects that are equal and wondering what will be the result of set.contains
let second = SimpleStruct(string: "a", number: 3)
print(first == second) // returns true
set.contains(second)
And wonders of wonders, launching a couple of times the playground, I got different results and this might cause unpredictable results ... Adding
var hashValue: Int {
return string.hashValue
}
it gets rid of any unexpected results but my doubt is:
Why, without the custom hashValue
implementation, ==
sometimes gets called and sometimes it doesn't?
Should Apple avoid this kind of unexpected behaviours?