导出具有可变成员的 Julia 结构的相等性

问题描述

在下面的 Julia 代码中,由于 T{BigInt}一个可变结构,我们的相等性不适用于 BigInt。然而,==BigInt 为自己明确定义。

julia> struct T{X}
           x :: X
       end

julia> T{Int64}(1) == T{Int64}(1),T{Int64}(1) === T{Int64}(1)
(true,true)

julia> T{BigInt}(1) == T{BigInt}(1),T{BigInt}(1) === T{BigInt}(1)
(false,false)

julia> T{BigInt}(1).x == T{BigInt}(1).x,T{BigInt}(1).x === T{BigInt}(1).x
(true,false)

有没有办法:

  • 为这些类型的结构自动生成一个 ==,它只是在每个字段上递归 ==
  • 或者将可变结构的不可变版本作为成员(如 C++ 中的 const),而不是使用与 BigInt 等效的不可变结构?

我的目标是避免在包含大量此类结构的包中使用样板。

解决方法

这应该有效:

function my_equals(a::S,b::S) where S
    for name in fieldnames(S)
        if getfield(a,name) != getfield(b,name)
            return false
        end
    end
    return true
end

我尝试通过

重载==
import Base.==

function ==(a::S,name)
            return false
        end
    end
    return true
end

这具有预期的行为,但(不出所料)似乎破坏了一些东西(即,在像这样重新定义 exit() 之后,您甚至不能调用 ==)。

如果您想使用 ==,那么您可以让所有自定义 struct 都继承自某种抽象类型,如下所示:

abstract type Z end

struct T{X} <: Z
    x::X
end

struct S{X} <: Z
    x::X
    y::X
end

import Base.==

function ==(a::V,b::V) where V <: Z
    for name in fieldnames(V)
        if getfield(a,name)
            return false
        end
    end
    return true
end

然后你就可以使用

julia> T{BigInt}(1) == T{BigInt}(1)
true

julia> S{BigInt}(2,5) == S{BigInt}(2,5)
true

julia> T{BigInt}(1) == T{BigInt}(2)
false

julia> S{BigInt}(2,3)
false

这不会干扰现有的 ==