I found it desirable to provide full control over the byte sequence that is fed to the hasher. Having a variety of overloads for all kinds of integer widths enables users to feed exactly as many bytes to the hasher as they have available, in as few combine
calls as possible. (However, it's not necessary to provide overloads for both unsigned and signed variants; it's safe to keep only one flavor.)
I agree! I would be nice to mark most combine(bits:)
overloads as @usableFromInline internal
; however, in the current implementation, combine(42 as UInt8)
and combine(bits: 42 as UInt8)
mean different things. To unify them, we first have to resolve the question of whether it's okay to allow
(42 as UInt8).hashValue != (42 as UInt64).hashValue
even though FixedWidthInteger
's heterogeneous ==
operator makes
(42 as UInt8) == (42 as UInt64)
My opinion is that we should allow this, because Hashable
doesn't (and shouldn't) set constraints on hashing behavior across distinct types. (The ==
above doesn't mean that UInt8
is "Equatable" to UInt64
.) However, we haven't really discussed this aspect of hashing yet, and there may be good reasons to make integer types hash the same. (The subtleties of AnyHashable
and NSNumber
semantics add some extra challenges to width-dependent hashes, but these seem tractable.)
Note that the combine(bits:)
overload that takes a UnsafeRawBufferPointer
is special; we'd want to keep that even if we remove the integer overloads. UnsafeRawBufferPointer
intentionally doesn't implement Hashable
.
It may also be possible to come up with a better name than combine(bits:)
. Suggestions are welcome!