在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"
Run Code Online (Sandbox Code Playgroud)
在下面的段落中:
该
!$运营商定型计算哈希值,编写自定义时,这是必要hash的过程。$!运算符的使用确保计算出的散列是唯一的。
我很难理解这一点。“完成”某事是什么意思?在这种情况下确保某些东西是独一无二的意味着什么?
如果不是阅读!$运算符的单一描述,而是查看哈希模块文档的开头,您的问题可能会得到解答。正如你在那里看到的,原始数据类型有一个hash()proc,它返回它们自己的哈希。但是,如果您有一个包含许多变量的复杂对象,您可能希望为该对象本身创建一个散列,您如何做到这一点?无需深入研究哈希理论,并将哈希视为黑匣子,您需要使用两种过程来生成有效的哈希:加法/串联运算符和终结运算符。因此,您最终使用!&将单个散列添加(或混合)到一个时间值中,然后使用!$来完成将该时间值转换为最终哈希值。如果 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
Run Code Online (Sandbox Code Playgroud)
至于为什么将哈希值临时连接然后最终确定,这在很大程度上取决于 Nim 开发人员选择使用哪种算法进行哈希。从源码中可以看出,hash concatenation 和 finalization 主要是位移位。不幸的是,源代码没有解释或指向任何其他参考资料来理解为什么这样做以及为什么与其他算法相比选择了这个特定的哈希算法。您可以尝试询问Nim 论坛,并根据您的发现改进文档/源代码。