【发布时间】:2017-03-06 13:34:33
【问题描述】:
我正在扩展 struct 以符合 Hashable。我将使用DJB2 哈希组合器来完成此操作。
为了方便为其他事情编写散列函数,我想扩展Hashable 协议,以便我的散列函数可以这样编写:
extension MyStruct: Hashable {
public var hashValue: Int {
return property1.combineHash(with: property2).combineHash(with: property3)
}
}
但是当我尝试编写实现 `combineHash(with:) 的 Hashable 扩展时,如下所示:
extension Hashable {
func combineHash(with hashableOther:Hashable) -> Int {
let ownHash = self.hashValue
let otherHash = hashableOther.hashValue
return (ownHash << 5) &+ ownHash &+ otherHash
}
}
…然后我得到这个编译错误:
/Users/benjohn/Code/Nice/nice/nice/CombineHash.swift:12:43: Protocol 'Hashable' 只能用作通用约束,因为它具有 Self 或关联的类型要求
这是 Swift 不允许我做的事情,还是我只是做错了并且收到了无用的错误消息?
Aside 来自 JAL 的评论链接到 a code review of a swift hash function,该评论也是由 Martin 撰写的,他在下面提供了接受的答案!他在那次讨论中提到了一个不同的哈希组合器,它基于 c++ boost 库中的一个。讨论真的很值得一读。替代组合器的冲突更少(在测试的数据上)。
【问题讨论】:
-
@JAL 不错的——里面有有用的信息!特别是 Swift 的哈希值类型是带符号的 int,所以我的代码会像这里给出的那样表现不佳!
-
是的,我遇到了类似的问题。 Martin 对 Boost hash combine 函数的 Swift 翻译是您工具箱中的一个很棒的函数。
-
@Benjohn:只有有符号整数的右移才能保留符号位。你的左移没有问题。
-
@MartinR 啊,好吧,我原来的哈希还不错吧? :-) 直到现在我才注意到您还编写了有关 Jal 链接到的哈希的代码审查!你们两个就像一个打击犯罪的二人组,防止碰撞并保持巨大的 O 期望 - 我感谢你们!