I am trying to make Base.unique
work with an array of a custom type. A really trivial example might look like this
import Base.isequal
struct TestStruct
x::String
end
Base.isequal(t1::TestStruct, t2::TestStruct) = length(t1.x) == length(t2.x)
#Should return just one element, instead returns exactly the input
unique([TestStruct("blah"), TestStruct("bluh")])
#Should return true, instead returns false
TestStruct("blah") == TestStruct("bluh")
I know unique(f, itr)
exists, but it won’t work well for my actual problem. I want to be able to extend Base.isequal
and have things like unique
and ==
call it. How is this done?
isequal
is the one that falls back on ==
, so you want to extend ==
.
The default implementation of isequal calls ==, so a type that does not involve floating-point values generally only needs to
define ==.
from isequal
’s docstring. Also from there is:
isequal(x,y) must imply that hash(x) == hash(y)
and unique
depends on this behaviour too. So defining Base.==
and Base.hash
should get you the behaviour you want:
julia> import Base: ==, hash
julia> ==(t1::TestStruct, t2::TestStruct) = length(t1.x) == length(t2.x)
== (generic function with 170 methods)
julia> TestStruct("blah") == TestStruct("bluh")
true
julia> hash(t::TestStruct) = unsigned(length(t.x))
hash (generic function with 69 methods)
julia> unique([TestStruct("blah"), TestStruct("bluh")])
1-element Vector{TestStruct}:
TestStruct("blah")
2 Likes