[swift-evolution] Refining SE-0185: Should providing a custom == suppress the default hashValue?

Howard Lovatt howard.lovatt at gmail.com
Fri Dec 15 21:36:39 CST 2017


In Java they have simple to use var arg library functions that equate and hash values. I have written similar in my own code. Something like:

    func equate<T0, T1>(_ e0: (T0, T0), _ e1: (T1, T1)) -> Bool where T0: Equatable, T1: Equatable {
        return e0.0 == e0.1 && e1.0 == e1.1
    }

Unfortunately in Swift I don’t think a var arg version is possible and the library would have to have versions up to some arity, say 7.

But it would mitigate the pain of manually writing hash and equate for the cases when the compiler written version isn’t available.

-- Howard.

> On 16 Dec 2017, at 8:11 am, Dave DeLong via swift-evolution <swift-evolution at swift.org> wrote:
> 
> @regexident has a long-standing proposal about how to do hashing better that would address this: 
> 
> https://gist.github.com/regexident/1b8e84974da2243e5199e760508d2d25
> 
> Dave
> 
>> On Dec 15, 2017, at 2:04 PM, T.J. Usiyan via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> Can we provide a 'standard' method/function that can be used to combine ordered hash values (`[Int] -> Int`)? That could make manually implementing `hashValue` less burdensome.
>> 
>> TJ
>> 
>>> On Fri, Dec 15, 2017 at 12:08 PM, Tony Allevato via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> 
>>>> On Fri, Dec 15, 2017 at 11:39 AM Howard Lovatt via swift-evolution <swift-evolution at swift.org> wrote:
>>>> +1
>>>> I think the simple solution of if you provide either == or hashValue you have to provide both is the best approach. Good catch of this bug.
>>>> -- Howard.
>>> 
>>> That would be a significant usability hit to a common use case. There are times where a value is composed of N fields where N is large-ish, and equality is dependent on the values of all N fields but the hash value only needs to be "good enough" by considering some subset of those fields (to make computing it more efficient).
>>> 
>>> That still satisfies the related relationship between == and hashValue, but a user wanting to explicitly implement a more efficient hashValue should *not* necessarily be required to explicitly write the same == that would be synthesized for them in that case.
>>> 
>>>  
>>>> 
>>>> > On 16 Dec 2017, at 6:24 am, Daniel Duan via swift-evolution <swift-evolution at swift.org> wrote:
>>>> >
>>>> > +1. The proposal wasn’t explicit enough to have either supported or be against this IMO. It’s a sensible thing to spell out.
>>>> >
>>>> > Daniel Duan
>>>> > Sent from my iPhone
>>>> >
>>>> >> On Dec 15, 2017, at 9:58 AM, Joe Groff via swift-evolution <swift-evolution at swift.org> wrote:
>>>> >>
>>>> >> SE-0185 is awesome, and brings the long-awaited ability for the compiler to provide a default implementation of `==` and `hashValue` when you don't provide one yourself. Doug and I were talking the other day and thought of a potential pitfall: what should happen if you provide a manual implementation of `==` without also manually writing your own `hashValue`? It's highly likely that the default implementation of `hashValue` will be inconsistent with `==` and therefore invalid in a situation like this:
>>>> >>
>>>> >> struct Foo: Hashable {
>>>> >> // This property is "part of the value"
>>>> >> var involvedInEquality: Int
>>>> >> // This property isn't; maybe it's a cache or something like that
>>>> >> var notInvolvedInEquality: Int
>>>> >>
>>>> >> static func ==(a: Foo, b: Foo) -> Bool {
>>>> >>   return a.involvedInEquality == b.involvedInEquality
>>>> >> }
>>>> >> }
>>>> >>
>>>> >> As currently implemented, the compiler will still give `Foo` the default hashValue implementation, which will use both of `Foo`'s properties to compute the hash, even though `==` only tests one. This could be potentially dangerous. Should we suppress the default hashValue derivation when an explicit == implementation is provided?
>>>> >>
>>>> >> -Joe
>>>> >> _______________________________________________
>>>> >> swift-evolution mailing list
>>>> >> swift-evolution at swift.org
>>>> >> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> > _______________________________________________
>>>> > swift-evolution mailing list
>>>> > swift-evolution at swift.org
>>>> > https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171216/4264994b/attachment.html>


More information about the swift-evolution mailing list