Nim 中的 !$(bang dollar)运算符是什么?

What is the !$ (bang dollar) operator in Nim?

Nim in Action 第 114 页定义自定义哈希函数的示例中,!$ 运算符用于 "finalize the computed hash"。

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"

在下面的段落中:

The !$ operator finalizes the computed hash, which is necessary when writing a custom hash procedure. The use of the $! operator ensures that the computed hash is unique.

我无法理解这一点。 "finalize" 是什么意思?在这种情况下确保某些东西是独一无二的是什么意思?

如果不阅读 !$ 运算符的单一描述,而是查看 beginning of the hashes module documentation. As you can see there, primitive data types have a hash() proc which returns their own hash. But if you have a complex object with many variables, you might want to create a single hash for the object itself, and how do you do that? Without going into hash theory, and treating hashes like black boxes, you need to use two kind of procs to produce a valid hash: the addition/concatenation operator and the finalization operator,您的问题可能会得到解答。因此,您最终使用 !& 继续将各个哈希值添加(或混合)到时间值中,然后使用 !$ 将时间值 finalize 为最终值哈希。如果 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 that hash concatenation and finalization is mostly bit shifting. Unfortunately the source code doesn't explain or point at any other reference to understand why is that done and why this specific hashing algorithm was selected compared to others. You could try asking the Nim forums,并根据您的发现改进 documentation/source 代码。