If I have arrays in a struct as below, I can't compare the equality of the struct because the arrays are mutable? Is there a way to get the equality to pass down to the array so that I get true
for a([1,2,3]) == a([1,2,3])
? Or is the only way to do this to extend Base.==
?
julia> struct a
v
end
julia> a([1,2,3]) == a([1,2,3])
false
julia> a(1) == a(1)
true
julia> [1,2,3] == [1,2,3] # want the equality to work like this for the struct
true
julia> [1,2,3] === [1,2,3]
false
The answer by @miguel raz does not work at all!
This happens since isequal
is actually calling ==
rather than ==
calling isequal
. In the isequal
doc you can find explicitely that:
The default implementation of
isequal
calls==
, so a type that does not involve floating-point values generally only needs to define==
Hence the correct code is:
struct A
v
end
import Base.==
==(x::A,y::A) = x.v==y.v
However, a more elegant approach would be to write a generic code that does not rely on having the field v
. Since we do not want to overload the default ==
operator we can define an abstract
type that will tell Julia to use our implementation:
abstract type Comparable end
import Base.==
function ==(a::T, b::T) where T <: Comparable
f = fieldnames(T)
getfield.(Ref(a),f) == getfield.(Ref(b),f)
end
Now you can define your own structures that will correctly compare:
struct B <: Comparable
x
y
end
Testing:
julia> b1 = B([1,2],[B(7,[1])]);
julia> b2 = B([1,2],[B(7,[1])])
julia> b1 == b2
true
As @Przemyslaw answered, an overload of ==
is needed.
For situations where an abstract class implementation doesn't work, the overload can be done as a one-liner (avoiding the import
statement):
Base.:(==)(a::A, b::A) = Base.:(==)(a.v, a.v)
It's good to also override isequal
(for structs that don't need special NaN and missing value semantics) and hash
(for structs that can be used as keys):
Base.isequal(a::A, b::A) = Base.isequal(a.v, b.v)
Base.hash(a::A, h::UInt) = Base.hash(a.v, h)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With