Julia复合类型中的哈希不稳定性

6
在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

从语言设计的角度来看,是否存在一些根本性的驱动因素促使这种行为出现?是否有修复或更正这种行为的计划?

1个回答

7
我不是Julia语言的设计师,但当比较可变和不可变值时,这种行为并不奇怪。您的类型是可变的:即使它们在字段b上具有相同的值,两个实例也不完全相同。如果您认为应该这样,可以自由地为其实现哈希函数。但一般来说,可变对象具有独立的身份。像这样的不可变实体之间无法区分,因此它们遵循结构哈希化是有意义的。
两个银行账户恰好有5美元在其中的情况并不相同,可能不应哈希为相同的数字。但两个$5的实例不可能彼此区分。

5
没错,这就是默认行为的原因。 - StefanKarpinski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接