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

Pyry Jahkola pyry.jahkola at iki.fi
Fri Jul 22 04:13:23 CDT 2016

> On 22 Jul 2016, at 04:11, Robert Widmann via swift-evolution <swift-evolution at swift.org> wrote:
> Harlan Haskins, Jaden Geller, and I have been working on a proposal to clean up the semantics of ordering relations in the standard library.  We have a draft that you can get as a gist.  Any feedback you might have about this proposal helps - though please keeps your comments on Swift-Evolution and not on the gist.

Bravo! It would be great to have Comparable defined in terms of a full comparison. I'd specifically call out String as a concrete example in the Motivation section, as this proposal is likely to give a performance boost on sorting String arrays, which is a pretty common thing to do.


I think the Detailed design section should explicitly show as source code:

1. What is the updated Equatable protocol?

2. What are all the updated operators? (I.e. show the new default implementations of `==` and `!=` too.)

3. In code comments, what are the updated rules or laws that should hold for Equatable and Comparable (and FloatingPoint, if any)?

4. What are the new "by: (Self, Self) -> Ordering" functions that the proposal is about to introduce to the stdlib?


On the topic of partial orderings (e.g. floating-point types), starting with the more important questions first:

5. Will it be considered "ok" to define a type for which `T.areSame(a, b) == true` but `a != b`? An obvious example would be Double.nan, so I assume the answer is a resounding yes.

6. Similarly, will it be "ok" to define a type for which `T.areSame(a, b) == false` but `a == b`? One possible example could be the comparison of `-0.0 <=> +0.0`. Should those be `.same` or not?

7. What, in fact, is the proposed total order for the stdlib's floating-point types?

(For an example, here is one possible way of defining `<=>` for Double, using `Double.bitPattern`. It distinguishes between +0.0 and -0.0, and even the various patterns of NaN! But do we want this for our `<=>` or something else?

    func <=> (lhs: Double, rhs: Double) -> Ordering {
      func f(_ x: UInt64) -> UInt64 {
        return x < 0x80000000_00000000 ? x + 0x80000000_00000000 : ~x
      return f(lhs.bitPattern) <=> f(rhs.bitPattern)
    print(            -0.0 <=> 0.0)         // ascending
    print(             1.0 <=> 0.0)         // descending
    print( Double.infinity <=> Double.nan)  // ascending
    print(-Double.infinity <=> -Double.nan) // descending
    print(      Double.nan <=> Double.nan)  // same

See http://swiftlang.ng.bluemix.net/#/repl/5791db33719d5d045b4d430c for a running example.)


A general idea:

8. I wouldn't mind if the proposal also covered including generated definitions for `tuple1 <=> tuple2` of tuples from zero arity through to 6 or whatever the gyb's upper limit may be.

That would simplify the example implementation of Date down to:

    func <=> (lhs: Date, rhs: Date) -> Ordering {
      return (lhs.year, lhs.month, lhs.day)
         <=> (rhs.year, rhs.month, rhs.day)

9. Some of us were not satisfied with the name of `.areSame(_:_:)`. Let me just point out that it would be nice if the name aligned with whatever `Ordering.same` will be called.

-- Pyry

More information about the swift-evolution mailing list