My question is related to a user-defined function in dialing operations , but I think I can solve the problem:
How to choose a specific hash function? For example, if I want to perform a value-based mapping rather than link matching, and I want to see if any tuple is present (or just delete it):
my %data := SetHash.new: (1, 2), (3, 4); %data{$(1, 2)}:delete;
In C ++ or C #, I can provide a custom hash / compare function for the constructor. In C #, hashing by value will automatically happen if my data type is a struct (value type, not reference type). Perl 6 to some extent uses hashing of the type of Pair values ββ(if the pair does not contain containers), but I donβt see how to make it work for any other complex type.
On the one hand, I understand why this is not the safest operation - it is easy to identify objects whose hash code may change after they are inserted. But that did not stop .NET and C ++ STL from allowing custom hashing.
You can use the API (with the chain hashing logic created by this , originally from Boost):
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]};
And this will be the hashing role that the Perl 6 core library should provide if it does not already exist:
role Hasher[::T=Any] { method equals(T $a, T $b --> Bool) { ... }; method get-hash-value(T $obj) { ... } }
Solution:. Currently, the most sensible solution is to override the .WHICH class .WHICH , which serves as a hash value and is used to test equality. I gave an example of a hash key class that emulates a value here . This is almost as universal as a custom hash function for a hash object, since the key type can be declared when creating the hash. (This cannot be done for Set , since Set not parameterized.)