Hi sven,
Welcome to the Julia community!
The short answer is that you should also implement hash for your part struct. Citing isequal’s documentation:
This typically means that types for which a custom == or isequal method exists must implement a corresponding hash method (and vice versa).
If you add Base.hash(p::part) = hash(p.x), then x_prime in X.parts now indeed evaluates to true.
If you want some more context, Julia’s Sets are basically Dicts with Nothing values. In turn Dicts rely on hash tables. When you are then using in(x, X.parts), you’re checking that x is a key in X.parts.dict. To do this, you
- Compute the hash index of
xin theDict’s hash table. - Check that this slot is not empty.
- If a value in this slot indeed exists, compare it to
xusingisequal.
In your example the slot for x_prime not the same as that of x due to differing hashes. In fact, the spot is empty, so in will immediately return false, without ever calling isequal. So even if you had written Base.:isequal(part1::part,part2::part) = true (and did not overwrite the default hash), you would find that x_prime in X.parts evaluates to false. Now, the documentation of in does state that
Sets check whether the item
isequalto one of the elements;
which is then actually a bit too simplistic, so the confusion is certainly understandable.