I am trying to understand why calling unique
in the following example returns a vector containing two elements which are equal as per isequal
:
struct Tag
tag::Int
end
Base.:(==)(t1::Tag,t2::Tag) = abs(t1.tag) == abs(t2.tag)
t1 = Tag(1); t2 = Tag(-1);
isequal(t1,t2) # true
v = unique([t1,t2]) # returns [t1,t2]
So it seems that v
contains both t1
and t2
, but isequal(t1,t2)
is true
, which seems puzzling to me given the documentation of unique
. Am I missing something?
If you look at the docstring if isequal
you read:
This typically means that types for which a custom ==
or isequal
method exists must
implement a corresponding hash
method (and vice versa).
similarly in the docstring of ==
you can read:
isequal
falls back to ==
, so new methods of ==
will be used by the Dict
type to compare keys. If your type will be used as a dictionary key, it should therefore also implement hash
.
The conclusion is that you should have implemented hash
method for your Tag
, which can be done e.g. like this (with this implementation hash of Tag
will be the same as hash of abs
of tag
field stored in it):
Base.hash(x::Tag, h::UInt) = hash(abs(x.tag), h)
And now you have:
julia> unique([t1,t2])
1-element Array{Tag,1}:
Tag(1)
5 Likes