[swift-evolution] [Draft][Proposal] Formalized Ordering

Pyry Jahkola pyry.jahkola at iki.fi
Fri Jul 22 14:26:36 CDT 2016


I agree with Tony that we should still keep == and != as part of Equatable, and<, <=, >, and >= as part of Comparable, while offering default implementations through <=>.

The reason is, that otherwise generic code would dispatch differently depending on the generic constraint; <T : Comparable> would only see the operators using <=> while <T : FloatingPoint> would pick up the IEEE-754 versions, even if in both cases T were Double.

Below is a concrete example where things wouldn't work as expected, given the proposal omitting the other operators in the protocols:

Dave Abrahams wrote:

>> In order to have an opinion on whether or not this is justified, I
>> need to know more about how areSame() may differ from == and how this
>> will affect generic code. What is required that could not fit inside
>> an override of Equatable?
> 
> Floating point types.  You should be able to ask for
> arrayOfFloats.firstIndex(of: x) even if there are NaNs in the array (or
> x).

Given that func firstIndex<T : Equatable>(of value: T) dispatches on Equatable, it would use Double.areSame(_:_:) instead of the IEEE-754 Double.==(_:_:). While that sounds innocuous, it would cause surprising results in the presense of negative zero:

    [-0.0, 1.0, .nan, 0.0].firstIndex(of: 0.0)
    //=> 3, not 0

which almost definitely isn't what the caller would want. Instead, functions like these should clearly document (or it should be obvious from their semantics) whether they use == and < (etc), or <=> in their implementation. I think that is a reasonable price to pay.

Or am I missing something obvious about round pegs and square holes?

— Pyry


More information about the swift-evolution mailing list