Use `Hashable.hash(into:)` or `Hasher.combine(_:)`?

Hasher's generic combine method is defined in Hasher.swift to simply call hash(into:) on its argument:

  @inlinable
  @inline(__always)
  public mutating func combine<H: Hashable>(_ value: H) {
    value.hash(into: &self)
  }

So hasher.combine(foo) is in fact just an alternative spelling for foo.hash(into: &hasher). They are completely equivalent. Choosing one or the other is a matter of aesthetic preference.

I personally prefer to use the generic combine, because it reads clearer to me. (I find that the inout argument makes hash(into:) rather noisy -- it's a sort of speed bump that makes my brain pause a bit whenever I see it.) This is why I left combine<H>(_:) in the proposal after we removed most of the other combine overloads. However, I can also see reasons for using hash(into:) directly, like Slava did in the WWDC session; after all, hasher.combine(_:) is one more thing you need to learn.

That said, while I do like combine(_:) better, I don't really like to use either form. I overwhelmingly prefer to just let the compiler implement hash(into:) for me automatically. I'd love to do that even more often!

8 Likes