<div dir="ltr">I like a lot of this, but the changes to Equatable are where I get stuck. What are the scenarios where areSame is useful *outside* the context of the proposed new Comparable interface?<div><br></div><div>I ask because changing the requirement for Equatable to areSame instead of == seems like a backwards change to me. There are plenty of unorderable types where == is the obvious thing you want to implement, and this makes it less obvious. It also adds a named method to a protocol to serve the purpose of an operator, which I&#39;ve been fighting hard against in SE-0091 (even though you keep the global one and delegate to it).</div><div><br></div><div>There are two concepts at play here: comparability and orderability. 99.99% of the time, they are identical. Your proposal mentions one place where they&#39;re not: IEEE floating point numbers, because there exists an element in that space, NaN, that doesn&#39;t satisfy an equivalence relation at all. But it&#39;s still reasonable to want a stable ordering with those included.</div><div><br></div><div>In the proposal as it&#39;s written right now, the individual inequality operators are implemented in terms of &lt;=&gt;. That won&#39;t work for FloatingPoint, because (NaN &lt; x) and (NaN &gt;= x) should both be false but the default implementations provided would make the latter true. So FloatingPoint would still have to provide its own implementations of *all of the (in)equality operators*, not just ==, in order to have the correct definition w.r.t. to IEEE 754. I didn&#39;t see that called out anywhere in the write-up.</div><div><br></div><div>That being said, don&#39;t get me wrong—there&#39;s still a lot about this proposal that I like :)  Here&#39;s what I&#39;m thinking (which is mostly what you have written, with some tweaks):</div><div><br></div><div>1) Don&#39;t change Equatable. I don&#39;t see a need to distinguish between equivalence and equality on its own (if there is one, please let me know!). As it stands today, I think the proposal &quot;leaks&quot; ordering concepts into Equatable when it shouldn&#39;t.</div><div>2) Comparable defines &lt;=&gt;, as proposed, but *also* defines &lt;, &gt;, &lt;=, &gt;=. A protocol extension provides defaults for &lt;, &gt;, &lt;=, &gt;=, ==, and != implemented in terms of &lt;=&gt;. This lets most implementors of Comparable implement &lt;=&gt; and get everything else for free, but it also lets types replace individual operators with customized implementations (see #4 below) easily *within* the type (SE-0091).</div><div>3) Comparable should be documented to imply that the default behavior is to link the behavior of &lt;=&gt; to the individual comparisons, but that it can be changed, meaning that only &lt;=&gt; must define a total ordering and the individual comparison operators need not.</div><div><span style="line-height:1.5">4) The very few types, like FloatingPoint, that need to provide domain-specific behavior to do the obvious/intended thing for users can and should override &lt;, &gt;, &lt;=, &gt;=, ==, and !=. This should be called out explicitly, and it would *not* affect ordering. I think it&#39;s entirely reasonable to have (NaN == NaN) return false and (NaN != NaN) return true but (NaN &lt;=&gt; NaN) return .same without introducing another areSame concept, because the former is demanded by IEEE 754.</span><br></div><div><div>5) Algorithms that rely on a total order, like sorts, must be implemented in terms of &lt;=&gt;, not in terms of the individual operators, because of the possibility that the definitions can be severed above.</div><div><br></div></div><div>As mentioned below, the one thing that a three-way comparison loses is the easy ability to pass &gt; instead of &lt; to reverse the ordering, but it&#39;s trivial to write a function that does this and I think it should be included as part of the proposal. Something like this (may be typos, I&#39;m writing it in Gmail):</div><div><br></div><div>public func reverse&lt;C: Comparable&gt;(ordering: (C, C) -&gt; Ordering) -&gt; (C, C) -&gt; Ordering {</div><div>  return { lhs, rhs in</div><div>    switch ordering(lhs, rhs) {</div><div>    case .ascending: return .descending</div><div>    case .descending: return .ascending</div><div>    case .same: return .same</div><div>  }</div><div>}</div><div><br></div><div>(Comedy alternative: Add a second operator, &gt;=&lt;. But that might be pushing it.)</div><div><br></div><div><br><div class="gmail_quote"><div dir="ltr">On Thu, Jul 21, 2016 at 6:11 PM Robert Widmann via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>Hello Swift Community,</div><div><br></div><div>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 <a href="https://gist.github.com/CodaFi/f0347bd37f1c407bf7ea0c429ead380e" target="_blank">get as a gist.</a>  Any feedback you might have about this proposal helps - though please keeps your comments on Swift-Evolution and not on the gist.</div><div><br></div><div>Cheers,</div><div><br></div><div>~Robert Widmann</div><div><br></div><div><br></div><div><br></div><div><br></div></div>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote></div></div></div>