作者:mobiledu2502883787 | 来源:互联网 | 2023-01-05 16:44
我的问题与集合操作中的用户定义函数有关,但我认为我可以切入问题的核心:
如何选择特定的散列函数?例如,如果我想进行基于值的匹配而不是引用匹配,并且我想查看某个元组是否存在(或者只是删除它):
my %data := SetHash.new: (1, 2), (3, 4);
%data{$(1, 2)}:delete; # False
在C++或C#中,我可以为构造函数提供自定义哈希/比较函数.在C#中,如果我的数据类型是a struct
(值类型而不是引用类型),则会自动按值进行散列.Perl 6在某种程度上进行了值类型哈希Pair
(如果Pair不包含任何容器),但我不知道如何使它适用于任何其他复杂类型.
一方面,我明白为什么这不是最安全的操作 - 很容易定义哈希代码插入后可以更改的对象.但这并没有阻止.NET和C++ STL允许自定义散列.
一种可能的API使用(与由激发了链式散列逻辑此,最初来自升压)将是:
class MyHasher does Hasher of Array[Int] {
method get-hash-value(Int @array) {
reduce
-> $a, $b {$a +^ ($b + 0x9e3779b97f4a7c16 + ($a +<6) + ($a +> 2))},
0,
|@array;
}
method equals(Int @a, Int @b) { @a eqv @b; }
}
my %data := SetHash.new(
my Int @=[1, 2], my Int @=[3, 4],
:hasher(MyHasher.new)
);
say %data{$[1, 2]}; # should be True
这将是另一个角色,它应该由Perl 6的核心库提供,如果它还不存在的话:
role Hasher[::T=Any] { method equals(T $a, T $b --> Bool) { ... }; method get-hash-value(T $obj) { ... } }
解决方案:目前,最合理的解决方案是覆盖类的.WHICH
方法,该方法用作哈希值并用于相等性测试.我举了一个哈希键类的例子,它在这里模拟了一个值类型.它几乎与每个哈希对象的自定义哈希函数一样通用,因为在创建哈希时可以声明键类型.(Set
由于Set
未参数化,因此无法完成此操作.)