在Julia中,具有至少一个具有相同值的字段的复合类型将散列到不同的值。这意味着如果将复合类型用作字典键或任何依赖于散列值的其他类型,则复合类型无法正常工作。此行为与其他类型的行为不一致,例如Vector {Int}。
更具体地说,
非复合类型的向量,它们是不同的对象但具有相同的值,并且散列到相同的值:
julia> hash([1,2,3])==hash([1,2,3])
true
没有字段散列为相同值的复合类型:
julia> type A end
julia> hash(A())==hash(A())
true
复合类型,如果它们是具有相同值的不同对象,则至少有一个字段哈希到不同的值:
julia> type B
b::Int
end
julia> hash(B(1))==hash(B(1))
false
但是,即使基础值发生变化,同一对象也会保持其哈希值:
julia> b=B(1)
julia> hash(b)
0x0b2c67452351ff52
julia> b.b=2;
julia> hash(b)
0x0b2c67452351ff52
这与向量的行为不一致(如果更改元素,则哈希值会更改):
julia> a = [1,2,3];
julia> hash(a)
0xd468fb40d24a17cf
julia> a[1]=2;
julia> hash(a)
0x777c61a790f5843f
不可变类型不存在此问题:
julia> immutable C
c::Int
end
julia> hash(C(1))==hash(C(1))
true
从语言设计的角度来看,是否存在一些推动这种行为的根本原因?是否有计划修复或纠正这种行为?
答案 0 :(得分:7)
我不是朱莉娅语言设计师,但我会说这种行为在比较可变和不可变的值时并不奇怪。您的类型B
是可变的:它的两个实例(即使它们对字段b
具有相同的值)并不完全是显而易见的,应该被视为相等。如果您认为应该是这种情况,您可以自由地为它实现哈希函数。但一般来说,可变对象具有独立的身份。像C
这样的不可变实体不可能彼此分开,因此它们服从结构哈希是有意义的。
两个碰巧有5美元的银行账户并不相同,可能不应该散列到相同的数字。但两个5美元的实例无法相互区分。