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
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
isequal
实际上调用的是==
而不是==
调用isequal
。在isequal
文档中,您可以明确找到以下内容:
“isequal
的默认实现调用==
,因此通常只需要定义涉及非浮点值的类型的==
。”
因此,正确的代码应该是:
struct A
v
end
import Base.==
==(x::A,y::A) = x.v==y.v
然而,更加优美的方法是编写一个通用代码,不依赖于字段v
。由于我们不想重载默认的==
运算符,我们可以定义一个abstract
类型,告诉Julia使用我们的实现:
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
现在您可以定义自己的结构体并进行正确比较:
struct B <: Comparable
x
y
end
测试:
julia> b1 = B([1,2],[B(7,[1])]);
julia> b2 = B([1,2],[B(7,[1])])
julia> b1 == b2
true
如@Przemyslaw所述,需要重载==
操作符。
对于抽象类实现无法满足的情况,可以将重载实现为一行代码(避免使用import
语句):
Base.:(==)(a::A, b::A) = Base.:(==)(a.v, a.v)
对于不需要特殊NaN和missing值语义的结构体,覆盖isequal
函数也是一种好方法,同时对于可以用作键的结构体,覆盖hash
函数也很重要:
Base.isequal(a::A, b::A) = Base.isequal(a.v, b.v)
Base.hash(a::A, h::UInt) = Base.hash(a.v, h)
function ==(a::T, b::T) where T <: Union{Comparable,SomeOtherType}
这样的内容。 - Przemyslaw Szufel