为具有可变成员的 Julia 结构派生相等性
Deriving equality for Julia structs with mutable members
在下面的 Julia 代码中,由于 BigInt
是可变结构,我们的等式不适用于 T{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, b::S) where S
for name in fieldnames(S)
if getfield(a, name) != getfield(b, 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) != getfield(b, 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, 5) == S{BigInt}(2, 3)
false
这不会干扰现有的 ==
。
在下面的 Julia 代码中,由于 BigInt
是可变结构,我们的等式不适用于 T{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, b::S) where S
for name in fieldnames(S)
if getfield(a, name) != getfield(b, 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) != getfield(b, 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, 5) == S{BigInt}(2, 3)
false
这不会干扰现有的 ==
。