<div dir="ltr">On Fri, Jul 22, 2016 at 9:57 PM, Dave Abrahams <span dir="ltr"><<a href="mailto:dabrahams@apple.com" target="_blank">dabrahams@apple.com</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-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="gmail-HOEnZb"><div class="gmail-h5"><br>
on Fri Jul 22 2016, Xiaodi Wu <<a href="http://xiaodi.wu-AT-gmail.com" rel="noreferrer" target="_blank">xiaodi.wu-AT-gmail.com</a>> wrote:<br>
<br>
> On Fri, Jul 22, 2016 at 9:46 PM, Dave Abrahams <<a href="mailto:dabrahams@apple.com">dabrahams@apple.com</a>> wrote:<br>
><br>
>><br>
>> on Fri Jul 22 2016, Xiaodi Wu <<a href="http://xiaodi.wu-AT-gmail.com" rel="noreferrer" target="_blank">xiaodi.wu-AT-gmail.com</a>> wrote:<br>
>><br>
>> > On Fri, Jul 22, 2016 at 9:23 PM, Matthew Johnson <<a href="mailto:matthew@anandabits.com">matthew@anandabits.com</a><br>
>> ><br>
>> > wrote:<br>
>> ><br>
>> >><br>
>> >> On Jul 22, 2016, at 9:17 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com">xiaodi.wu@gmail.com</a>> wrote:<br>
>> >><br>
>> >> On Fri, Jul 22, 2016 at 9:15 PM, Matthew Johnson via swift-evolution <<br>
>> >> <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br>
>> >><br>
>> >>><br>
>> >>> On Jul 22, 2016, at 9:04 PM, Dave Abrahams via swift-evolution <<br>
>> >>> <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br>
>> >>><br>
>> >>><br>
>> >>> on Fri Jul 22 2016, Matthew Johnson <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br>
>> >>><br>
>> >>> On Jul 22, 2016, at 8:37 PM, Xiaodi Wu via swift-evolution<br>
>> >>> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br>
>> >>><br>
>> >>> On Fri, Jul 22, 2016 at 8:20 PM, Dave Abrahams via swift-evolution<br>
>> >>> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
>> >>><br>
>> >>><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>>><br>
>> >>> wrote:<br>
>> >>><br>
>> >>> on Fri Jul 22 2016, Daniel Duan <daniel-AT-duan.org<br>
>> >>> <<a href="http://daniel-at-duan.org/" rel="noreferrer" target="_blank">http://daniel-at-duan.org/</a>>> wrote:<br>
>> >>><br>
>> >>> On Jul 22, 2016, at 3:00 PM, Dave Abrahams via swift-evolution<br>
>> >>> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>>><br>
>> >>> wrote:<br>
>> >>><br>
>> >>><br>
>> >>> on Fri Jul 22 2016, Daniel Duan<br>
>> >>> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>>>><br>
>> >>> wrote:<br>
>> >>><br>
>> >>><br>
>> >>> On Jul 22, 2016, at 11:05 AM, Dave Abrahams via swift-evolution<br>
>> >>> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>>>><br>
>> >>> wrote:<br>
>> >>><br>
>> >>><br>
>> >>> on Thu Jul 21 2016, Duan<br>
>> >>><br>
>> >>><br>
>> >>> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>>><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>><br>
>> >>> <mailto:<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a> <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>>>>><br>
>> >>> wrote:<br>
>> >>><br>
>> >>> Great proposal. I want to second that areSame may mislead user to<br>
>> >>> think this is about identity.<br>
>> >>><br>
>> >>> I like areEquivalent() but there may be better names.<br>
>> >>><br>
>> >>><br>
>> >>> It really *is* about identity as I posted in a previous message. But<br>
>> >>> that doesn't change the fact that areEquivalent might be a better name.<br>
>> >>> It's one of the things we considered; it just seemed long for no real<br>
>> >>> benefit.<br>
>> >>><br>
>> >>><br>
>> >>> If the addresses of the arguments aren’t being used, then we don’t<br>
>> >>> consider<br>
>> >>> them part of their *identity*. I can follow this logic. My fear is most<br>
>> >>> users<br>
>> >>> won’t make this leap on their own and get the same initial impression<br>
>> as<br>
>> >>> I did.<br>
>> >>> It's entirely possible this fear is unfounded. Some educated<br>
>> bikesheding<br>
>> >>> wouldn't hurt here IMO :)<br>
>> >>><br>
>> >>><br>
>> >>> Well, it's still a very real question whether we ought to have the<br>
>> >>> additional API surface implied by areSame, or wether we should collapse<br>
>> >>> it with ===.<br>
>> >>><br>
>> >>><br>
>> >>> To spell this out (because I had to think about it for a second): ===<br>
>> >>> will be derived from<br>
>> >>> <=>,<br>
>> >>> but also becomes default implementation for ==, which remains open for<br>
>> >>> customization.<br>
>> >>><br>
>> >>><br>
>> >>> I was imagining roughly this (untested):<br>
>> >>><br>
>> >>> /// Two references are identical if they refer to the same<br>
>> >>> /// instance.<br>
>> >>> ///<br>
>> >>> /// - Note: Classes with a more-refined notion of “identical”<br>
>> >>> /// should conform to `Identifiable` and implement `===`.<br>
>> >>> func ===(lhs: AnyObject, rhs: AnyObject) -> Bool {<br>
>> >>> ObjectIdentifier(lhs) == ObjectIdentifier(rhs)<br>
>> >>> }<br>
>> >>><br>
>> >>> /// Supports testing that two values of `Self` are identical<br>
>> >>> ///<br>
>> >>> /// If `a` and `b` are of type `Self`, `a === b` means that<br>
>> >>> /// `a` and `b` are interchangeable in most code. A conforming<br>
>> >>> /// type can document that specific observable characteristics<br>
>> >>> /// (such as the `capacity` of an `Array`) are inessential and<br>
>> >>> /// thus not to be considered as part of the interchangeability<br>
>> >>> /// guarantee.<br>
>> >>> ///<br>
>> >>> /// - Requires: `===` induces an equivalence relation over<br>
>> >>> /// instances.<br>
>> >>> /// - Note: conforming types will gain an `==` operator that<br>
>> >>> /// forwards to `===`.<br>
>> >>> /// - Note: Types that require domain-specific `==`<br>
>> >>> /// implementations with different semantics (e.g. floating<br>
>> >>> /// point) should define a more-specific overload of `==`,<br>
>> >>> /// which will be used in contexts where the static type is<br>
>> >>> /// known to the compiler.<br>
>> >>> /// - Note: Generic code should usually use `==` to compare<br>
>> >>> /// conforming instances; that will always dispatch to `===`<br>
>> >>> /// and will be unaffected by more specific overloads of<br>
>> >>> /// `==`.<br>
>> >>> protocol Identifiable { // née Equatable name is negotiable<br>
>> >>> func ===(_: Self, _: aSelf) -> Bool<br>
>> >>> }<br>
>> >>><br>
>> >>> /// Default definition of `==` for Identifiable types.<br>
>> >>> func ==<T: Identifiable>(lhs: T, rhs: T) -> Bool {<br>
>> >>> return lhs === rhs<br>
>> >>> }<br>
>> >>><br>
>> >>> /// Conforming types have a default total ordering.<br>
>> >>> ///<br>
>> >>> /// If `a` and `b` are of type `Self`, `a <=> b` means that<br>
>> >>> /// `a` and `b` are interchangeable in most code. A conforming<br>
>> >>> /// type can document that specific observable characteristics<br>
>> >>> /// (such as the `capacity` of an `Array`) are inessential and<br>
>> >>> /// thus not to be considered as part of the interchangeability<br>
>> >>> /// guarantee.<br>
>> >>> ///<br>
>> >>> /// - Requires: `<=>` induces a total ordering over<br>
>> >>> /// instances.<br>
>> >>> /// - Requires: the semantics of `<=>` are consistent with<br>
>> >>> /// those of `===`. That is, `(a <=> b) == .equivalent`<br>
>> >>> /// iff `a === b`.<br>
>> >>><br>
>> >>> For floating point, I'd hope that `a === b` if `(a <=> b) == .same`<br>
>> *but<br>
>> >>> not iff*. This is to satisfy IEEE 754: "Comparisons shall ignore the<br>
>> sign<br>
>> >>> of zero (so +0 = −0)”.<br>
>> >>><br>
>> >>><br>
>> >>> The point of this design is that `===` means identity and that `.same `<br>
>> >>> also means identity.<br>
>> >>><br>
>> >>> Since this is new territory I suppose we get to decide what identity<br>
>> >>> means for floating point. Should +0 and -0 have the same identity or<br>
>> >>> not? I’ll leave the answer to folks more knowledgable about numerics<br>
>> >>> than I.<br>
>> >>><br>
>> >>><br>
>> >>> It's settled law<br>
>> >>><br>
>> <a href="https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate" rel="noreferrer" target="_blank">https://en.wikipedia.org/wiki/IEEE_floating_point#Total-ordering_predicate</a><br>
>> >>> :-)<br>
>> >>><br>
>> >>><br>
>> >>> Yes, assuming we want to define identity in terms of the IEEE<br>
>> definition<br>
>> >>> of total ordering.<br>
>> >>><br>
>> >><br>
>> >> I see what you're saying here. That could work. Comparable `===` and<br>
>> >> Equatable `<=>` could do its own thing, and FloatingPoint<br>
>> >> `isTotallyOrdered(below:)` can preserve the IEEE definition of total<br>
>> >> ordering<br>
>> >><br>
>> >><br>
>> >> Actually, I was hinting at your argument that `===` true iff `<=>` same<br>
>> >> shouldn’t be a semantic requirement of the protocols.<br>
>> >><br>
>> >> This is another option, but I don’t think it’s going to fly. It seems<br>
>> >> reasonable to assume that `<=>` will have IEEE semantics. We will trip<br>
>> a<br>
>> >> lot of people up if it doesn’t. That’s a big reason we can’t consider<br>
>> >> changing floating point `==` to define an equivalence relation.<br>
>> >><br>
>> ><br>
>> > Actually, here I doubt it. The total ordering isn't exposed as part of<br>
>> any<br>
>> > comparison operator defined in the IEEE spec. In fact, the total ordering<br>
>> > wasn't introduced until a (fairly) recent IEEE revision, IIUC. Breaking<br>
>> > `==` would definitely cause people to jump, but `<=>` needn't be the IEEE<br>
>> > totalOrder predicate IMO.<br>
>><br>
>> Wait, I thought we were saying that `<=>` could be IEEE totalOrder, and<br>
>> `===` could be like `==` but with well-behaved NaNs, so it's still an<br>
>> equivalence relation, thus declaring the signedness of 0 to be<br>
>> inessential.<br>
>><br>
><br>
> I was (that was the "=== if but not iff <=>" business above), then I<br>
> thought Matthew was saying something different and agreed with him.<br>
><br>
> What I thought that Matthew thought was actually very insightful. He didn't<br>
> actually think this, apparently, but: IEEE totalOrder does exactly what it<br>
> says on the tin. But, it is not useful for any generic comparisons or (as<br>
> far as I'm aware) any generic sorting algorithms. I cannot conceive of a<br>
> numeric algorithm or a generic algorithm that relies on two equal floating<br>
> point values being ordered based on their binary representation. We should<br>
> have some way of exposing totalOrder to a user of a BinaryFloatingPoint<br>
> type, but I don't know that it should be the basis for floating point<br>
> *identity* with respect to protocol conformance. It's explicitly *not* what<br>
> IEEE recommends for comparison anyway.<br>
<br>
</div></div>That makes sense. Perhaps IEEE hasn't actually made a principled<br>
decision about which aspects of floating point numbers are essential,<br>
and we have to do it for them.<br></blockquote><div><br></div><div>I may have to walk back some comments. IEEE totalOrder rules should work fine for <=> if we relax "a === b iff (a <=> b) == .same", as it explicitly states:</div><div><br></div><div><div>a) If x < y, totalOrder(x, y) is true. [i.e. compares ascending]</div><div>b) If x > y, totalOrder(x, y) is false. [i.e. does not compare ascending]</div></div><div><br></div><div>This is where Steve's expertise comes in. In either case, I think we might have a solution for `===` behaving weirdly in generic algorithms.</div><div><br></div></div></div></div>