【发布时间】:2015-10-05 23:43:19
【问题描述】:
我怎样才能散列成对或三元组的 'eq-able 对象,如符号或整数?
在 python 中,我可以使用元组作为字典键,有没有办法在 lisp 中做到这一点而不诉诸“相等测试”?
【问题讨论】:
标签: hash tuples common-lisp hashtable
我怎样才能散列成对或三元组的 'eq-able 对象,如符号或整数?
在 python 中,我可以使用元组作为字典键,有没有办法在 lisp 中做到这一点而不诉诸“相等测试”?
【问题讨论】:
标签: hash tuples common-lisp hashtable
虽然某些实现可能会为自定义哈希表函数提供规定,但该标准仅定义了四个:
18.1.1 Hash-Table Operations
哈希表有四种:key与eq比较、key与eql比较、key为 与equal比较,以及key与equalp比较的那些。
这意味着如果您想使用标准哈希表,那么您可能需要使用 equal 或 equalp 哈希表。我确实注意到您写道:
我怎样才能散列成对或三元组的 'eq-able 对象,如符号或 整数?
虽然可以用 eq 可靠地比较符号,但您不应该用 eq 比较数字。 eq 的文档说:
具有相同值的数字不必是 eq, ... 允许实现随时“复制”字符和数字。结果是 Common Lisp 不保证 eq 为真,即使它的两个参数都是“相同的东西”,如果那个东西是字符或数字的话。
并给出这个例子:
(eq 3 3)
; => true
; OR=> false
但是,如果您正在使用整数的(小)元组,则可以轻松地对它们的函数进行哈希处理。例如,元组 (a,b,c) 可以映射到 2a×3b×5c。由于这样的函数会生成与 可与 eql 相媲美的唯一数字,因此您可以使用 eql 哈希表。
这种映射函数的另一个选项(也适用于符号)是使用sxhash。这是一个标准的散列函数,应该为 equal 值产生相同的值。它是如何工作的,以及它究竟做了什么并没有真正具体说明,但它的优点是它在相同实现的 Lisp 映像中是稳定的(例如,今天和明天运行一个版本的 SBCL,以及 sxhash 将为 equal 对象返回相同的结果)。当然,一个等值哈希表可能已经在为您执行此操作,因此您的里程可能会有所不同。
【讨论】:
eql 在这里似乎就足够了,但在你的答案中包含这个函数可能会很有趣。另见:cneufeld.ca/genie/blog/2014/07/…