[swift-evolution] Universal Equatability, Hashability, and Comparability

Tony Allevato allevato at google.com
Tue May 24 11:46:43 CDT 2016


This is something I've wanted for a while (ever since basic equality was
added to tuples), and I've considered writing a proposal but never had the
time to jot something down. I'm glad other people have had the same
thoughts. I've become frustrated at having to write the switch-case-let
boilerplate for enums, especially.

I'd like to see the following rules:

For structs:
- A struct should implicitly conform* to Equatable if all of its fields
conform (either explicitly or implicitly by these rules) to Equatable. The
compiler will auto-generate an implementation that is simply the AND of the
field-wise comparisons.
- A struct should implicitly conform to Hashable if all of its fields
conform (exp. or imp.) to Hashable. The compiler will auto-generate an
implementation that computes a hash value using a universal hash function
(say, Knuth's) based on the hash values of its fields. (Order matters here,
so declaration order?)

For enums:
- An enum should implicitly conform to Equatable if all of the types of all
associated values across all cases conform to Equatable. The compiler will
auto-generate an implementation that switches on the case and if they are
the same, compares the associated values.
- An enum should implicitly conform to Hashable if all of its fields
conform (exp. or imp.) to Hashable. The compiler will auto-generate an
implementation that computes a hash value using a universal hash value
where the first term is the case's ordinal (position in declaration order)
followed by terms coming from its associated values' hash values.

I'm not 100% sold on Comparable being a good idea to support here; when
implementing Comparable over multiple fields, there's often a specific
order that matters—you encounter a pair of fields that are equal so you
move on to the next one. I don't think we want to tie that to field
declaration order or anything like that... it seems to surprising. But it
would be nice to get rid of that boilerplate as well.

* When I say "implicitly conform" above, I'm torn about whether that should
mean:
- the struct or enum doesn't have to list Equatable/Hashable at all, but it
gets it anyway (kind of like how enums that extend a scalar type get
RawRepresentable automatically), or
- the struct or enum gets implicit implementations of ==/hashValue, but you
still have to explicitly declare that it conforms to Equatable/Hashable

On the one hand, getting the conformance implicitly matches how
RawRepresentable is already treated, and makes getting the conformance zero
effort. On the other hand, it makes error handling trickier: if you add a
non-Equatable/non-Hashable field or associated value to a struct/enum, all
of your call sites break. (I guess they would even if you declared the
conformance, but at least there you'd also get the "Type does not conform
to Equatable/Hashable" error at the struct/enum itself, and the compiler
could even potentially flag the offending field/associated value that's
causing the conformance to fail.) Thoughts?

If there's interest, I'd be happy to put this into the actual proposal
template.


On Tue, May 24, 2016 at 8:46 AM Mark Sands via swift-evolution <
swift-evolution at swift.org> wrote:

> I apologize upfront for necromancing this thread. Is there any momentum on
> this proposal?
>
> My team was discussing the merits of default (opt-in) Equality. As soon as
> the equality function has been written then the compiler is satisfied, but
> there is no way to get compile time correctness for the equality. Unit
> tests can only go so far with ensuring the equality function is robust.
> Once a new property is added to a struct, for instance, the equality
> function is no longer correct and without warning. Currently there is no
> way to safeguard this situation. This would be a welcome addition to Swift.
>
> Mark
>
> On Fri, Mar 11, 2016 at 11:19 AM, Jose Cheyo Jimenez via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> > (starting a new thread by DaveA's request)
>> >
>> > There's a definition of equality that makes sense as a default for
>> nearly every type in our system:
>> >
>> > - Basic types like IntNN, FloatNN, String, etc. have domain-defined
>> equality,
>> > - Structs and tuples can be considered equal if their corresponding
>> fields are equal,
>> > - Enums can be considered equal if they carry the same, equal payload,
>>
>> +1 for Equality, Comparable and Hashable especially for enums and tuples.
>>
>> I know that equality was added for tuples but I think that enums are
>> perfect for adding automatic generation of conformance to Equality,
>> Comparable and Hashable.
>>
>> Take a look at this toy example of an Enum with 9 cases
>>
>> boiler plate to conform to Equatable
>>
>> https://github.com/exercism/xswift/blob/master/exercises/poker/PokerExample.swift#L151-L189
>>
>> boiler plate to conform to Comparable
>>
>> https://github.com/exercism/xswift/blob/master/exercises/poker/PokerExample.swift#L191-L245
>>
>>
>> > It's my feeling that Equatable and Hashable would make a lot of sense
>> as universal operations; I'm not so sure about Comparable.
>> >
>> > -Joe
>>
>> For enums a defaultComparable protocol could just rank on the order the
>> fields are declared:
>>
>> https://github.com/exercism/xswift/blob/master/exercises/poker/PokerExample.swift#L211-L212
>>
>>
>>
>> _______________________________________________
>> 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/20160524/92a46cab/attachment-0001.html>


More information about the swift-evolution mailing list