在Nim in Action的第114页上定义自定义散列函数的示例中,!$
运算符用于"最终确定计算的散列"。
import tables, hashes
type
Dog = object
name: string
proc hash(x: Dog): Hash =
result = x.name.hash
result = !$result
var dogOwners = initTable[Dog, string]()
dogOwners[Dog(name: "Charlie")] = "John"
在以下段落中:
!$
运算符最终确定计算的哈希值,这在编写自定义hash
过程时是必需的。使用$!
运算符可确保计算的哈希值是唯一的。
我无法理解这一点。什么意思到"最终确定"什么?在这种情况下确保某些东西是独一无二的是什么意思?
答案 0 :(得分:3)
如果您没有阅读!$
运营商的单一说明,而是查看beginning of the hashes module documentation,那么您的问题可能会得到解答。正如您所看到的,原始数据类型具有hash()
proc,它返回自己的哈希值。但是如果你有一个包含许多变量的复杂对象,你可能想为对象本身创建一个哈希,你怎么做呢?如果不进入哈希理论,并处理像黑盒一样的哈希,你需要使用两种过程来产生一个有效的哈希:addition/concatenation operator和finalization operator。因此,您最终使用!&
将各个哈希值添加(或混合)为时间值,然后使用!$
将最终确定该时间值转换为最终哈希值。如果Dog对象有多个变量,那么Nim in Action示例可能更容易理解,因此需要使用两个运算符:
import tables, hashes, sequtils
type
Dog = object
name: string
age: int
proc hash(x: Dog): Hash =
result = x.name.hash !& x.age.hash
result = !$result
var dogOwners = initTable[Dog, string]()
dogOwners[Dog(name: "Charlie", age: 2)] = "John"
dogOwners[Dog(name: "Charlie", age: 5)] = "Martha"
echo toSeq(dogOwners.keys)
for key, value in dogOwners:
echo "Key ", key.hash, " for ", key, " points at ", value
至于为什么哈希值暂时连接然后最终确定,这很大程度上取决于Nim开发人员选择用于散列的算法。您可以看到from the source code哈希连接和最终确定主要是位移。不幸的是,源代码没有解释或指出任何其他参考,以了解为什么这样做以及为什么选择这个特定的哈希算法与其他算法相比。您可以尝试询问Nim forums,并根据您的发现改进文档/源代码。