<div dir="ltr">On Sun, Apr 16, 2017 at 1:13 AM, Dave Abrahams via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div class="gmail-HOEnZb"><div class="gmail-h5"><snip> </div></div></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div><div class="gmail-h5">
>> > I have an incipient idea. It begins with:<br>
>> ><br>
>> > enum ComparisonResult {<br>
>> > case orderedAscending, orderedSame, orderedDescending, unordered<br>
>> > }<br>
>> ><br>
>> > I am sure there is something I am missing which makes this design a<br>
>> > horrible idea, but I'm interested in hearing them.<br>
>><br>
>> It's not a horrible idea, but to be fair it's not really a design yet,<br>
>> either. You haven't said anything about what it's supposed to mean, how<br>
>> it is supposed to be used, how people write, use, and compose generic<br>
>> algorithms with it, how it deals with floating point, etc.<br>
>><br>
><br>
> I've evolved my thinking based on the discussion. Let's see:<br>
><br>
> ```<br>
> public enum ComparisonResult : Equatable {<br>
> case orderedAscending, equivalent, orderedDescending, unordered<br>
> // I have renamed one case, in the hopes of emphasizing that two values<br>
> // that compare `equivalent` are not merely ordered the same, but should<br>
> // satisfy the three conditions of an equivalence relation.<br>
> }<br>
> // I will have to leave the question of how to bridge from Obj-C<br>
> // NSComparisonResult up to more capable hands.<br>
><br>
> public protocol Comparable : Equatable {<br>
> func compared(to other: Self) -> ComparisonResult<br>
> }<br>
> // This will have to be modified as necessarily to support compiler magic<br>
> // necessary for source-compatibility with Swift 3<br>
><br>
> extension Comparable {<br>
> public static func == (lhs: Self, rhs: Self) -> Bool {<br>
> let comparison = lhs.compared(to: rhs)<br>
> precondition(comparison != .unordered)<br>
> return comparison == .equivalent<br>
> }<br>
><br>
> public static func < (lhs: Self, rhs: Self) -> Bool {<br>
> let comparison = lhs.compared(to: rhs)<br>
> precondition(comparison != .unordered)<br>
> return comparison == .orderedAscending<br>
> }<br>
> // etc.<br>
><br>
> // Something I thought I'd never want to see, but on reflection not<br>
> terrible:<br>
> public static func &== (lhs: Self, rhs: Self) -> Bool {<br>
> return lhs.compared(to: rhs) == .equivalent<br>
> }<br>
><br>
> public static func &< (lhs: Self, rhs: Self) -> Bool {<br>
> return lhs.compared(to: rhs) == .orderedAscending<br>
> }<br>
> // etc.<br>
> }<br>
><br>
> extension FloatingPoint : Comparable {<br>
> public func compared(to other: Self) -> ComparisonResult {<br>
> if isNaN || other.isNaN { return .unordered }<br>
> if isLess(than: other) { return .orderedAscending }<br>
> if other.isLess(than: self) { return .orderedDescending }<br>
><br>
> // On reconsideration, probably actually least surprising if +0.0 ==<br>
> -0.0<br>
> // no matter what. It does not matter that division can give different<br>
> // results for two equivalent values, only that the three rules of an<br>
> // equivalence relation will hold, and it does.<br>
> //<br>
> // If a user is really savvy to the sign of zero, there is<br>
> FloatingPoint.sign,<br>
> // which is necessary in any case for working with FP operations that<br>
> // distinguish between +0 and -0. I can't think of a generic algorithm<br>
> over<br>
> // all Comparable types that could make use of the distinction between<br>
> +0<br>
> // and -0.<br>
> return .equivalent<br>
> }<br>
> }<br>
> ```<br>
><br>
> In this design, `==`, `<`, etc. correspond to IEEE "signaling" operators,<br>
> while `&==`, `&<`, etc. correspond to C-style operators, which IEEE calls<br>
> "quiet" and actually notates using "?==", "?<", etc.<br>
<br>
</div></div>It's interesting, but what's missing here is a description of the user<br>
model. How do users program with this design? What should my<br>
expectations be w.r.t. generic algorithms like sort() and floating point<br>
numbers, particularly NaN? If, as I suspect, sorting a collection<br>
containing NaN is going to trap (unless the collection has only one<br>
element?), why is that the right behavior?</blockquote><div><br></div><div>I've spent some time fleshing out this idea:</div><div><a href="https://gist.github.com/xwu/e864ffdf343160a8a26839388f677768">https://gist.github.com/xwu/e864ffdf343160a8a26839388f677768</a></div><div><br></div><div><br></div></div></div></div>