<div dir="ltr">On Sat, Apr 15, 2017 at 3:12 PM, Dave Abrahams via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
on Thu Apr 13 2017, Xiaodi Wu &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br>
<br>
&gt; Getting this sorted out is definitely a worthwhile effort. I do have<br>
&gt; thoughts about this proposal:<br>
&gt;<br>
&gt; I continue to have reservations about an identical spelling (e.g. `==`)<br>
&gt; giving two different answers with the same values of the same type,<br>
&gt; depending on the generic context. It is a very *clever* design, but it is<br>
&gt; also a very *subtle* behavior that I can see leading to much confusion and<br>
&gt; befuddlement for any user who is not well versed *both* in the intricacies<br>
&gt; of IEEE floating point *and* in the intricacies of Swift.<br>
<br>
</span>I can&#39;t help but think that the concern over confusion here is not<br>
informed by any realistic situations.  Please describe<span class=""><br></span></blockquote><div><br></div><div>To be clear, I&#39;m not claiming that my concerns about the proposal outweigh my enthusiasm for it.</div><div><br></div><div>But here, the confusion I&#39;m concerned about stems from the essential conclusion by the proposal authors that types (including, but not necessarily only limited to FP types) which are ordinarily compared in a way that treats certain &quot;special values&quot; differently must also present an alternative notion of comparison that accounts for all possible values. The special casing of certain values already makes comparison operations difficult to understand; I guess I&#39;m simply stating what is unavoidably true, that having a &quot;non-special-cased&quot; comparison *in addition* to that adds additional difficulty.</div><div><br></div><div>One example where this comes to mind is this: `XCTAssertEqual(+0.0, -0.0)` will pass or fail depending on whether XCTAssertEqual provides a FP-specific specialization. This is something that cannot be determined by reading the testing code itself: that is, it requires not merely knowledge about whether or not the call site &quot;knows&quot; that it&#39;s operating on a FP type, but also knowledge about whether XCTest itself is FP-aware.</div><div><br></div><div>The issue increases in difficulty when it comes to non-stdlib types. Suppose I were to write a Rational type. (I am writing a Rational type, but we can talk about that later.) This Rational type is capable of representing NaN (`(0 / 0 as Rational&lt;Int&gt;).isNaN == true`) and, for consistency with FP types, `Rational&lt;Int&gt;.nan != Rational&lt;Int&gt;.nan`. If this proposal is implemented, *I* would be responsible for making XCTest Rational-aware, vending `XCTAssertEqual&lt;Rational&lt;T&gt;&gt;(_:_:)`. In fact, to ensure that users of Rational get the expected behavior everywhere, I would have to vend special Rational-aware versions of every stdlib, core library, and _third-party_ function that is FP-aware, which it is not possible to do.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
&gt; Actually, the fact that this behavior cannot even be achieved without<br>
&gt; currently non-existent compiler features means that it is not possible<br>
&gt; to understand what&#39;s truly going on without reading *this document*,<br>
<br>
</span>This doesn&#39;t seem like a reasonable argument.  New compiler features get<br>
documented outside of the proposals they come from.  Nobody&#39;s going to<br>
have to go read a proposal to understand what @implements means.</blockquote><div><br></div><div>I do not mean that I seriously believe @_implements will never be documented. (Although, as an underscored attribute, it does not need to be documented outside of the apple/swift repo, in the same way that @_transparent and its ilk are not documented outside the repo.) I am simply saying that fully understanding how `Comparable` and `FloatingPoint` interact with each other will require learning one additional advanced feature of the language than is required now, and that this feature does not even currently exist.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
&gt; after mastering *both* IEEE floating point *and* Swift<br>
&gt; generics/protocols/extensions/<wbr>static vs. dynamic dispatch. All to use<br>
&gt; `==` correctly.<br>
<br>
</span>I don&#39;t understand this argument.  The *whole* point of this proposal is<br>
that you use `==` correctly *without* the need for any special knowledge.<br>
<span class=""><br>
&gt; Which is to say, most people will simply not even know if they happen<br>
&gt; to be using the `==` they did not intend to use.<br>
<br>
</span>Most people aren&#39;t aware that IEEE comparison is quirky and don&#39;t know<br>
what they intend with respect to those semantics, but anyone who *is*<br>
aware of his intention has an easy way to understand what&#39;s happening.<br>
Does this code know it&#39;s operating on floating point numbers?  If so,<br>
it&#39;s IEEE.  If not, it&#39;s an equivalence relation.<br>
<span class=""><br>
&gt; I think consideration should be given to a design that achieves a<br>
&gt; user-facing but not onerous differentiation between level 1 and level 2<br>
&gt; equality. However, the only one I can think of is essentially a different<br>
&gt; shade of the `PartiallyComparable` alternative already outlined in the<br>
&gt; document.<br>
<br>
</span>I am *deeply* opposed to such a protocol.  It is purely syntactic in<br>
nature and thus useless for correctly constraining generic algorithms.<br></blockquote><div><br></div><div>But there do exist types for which some pairs of values cannot be compared to each other. A generic algorithm that blows up if a value cannot be compared to another value should not operate on such types, no?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
People will use it anyway, resulting in algorithms that statically<br>
accept, but are incorrect for, floating point.  In my opinion there&#39;s<br>
only one feasible answer that doesn&#39;t use the static/dynamic distinction<br>
we&#39;ve proposed: throw IEEE semantics under the bus, making it available<br>
only under a different syntax.<br>
<br>
This would be a drastic move whose primary downside is that floating<br>
point code ported from C would need to be carefully audited and may<br>
become less easy to read.  But at least it would be viable.<span class=""><br></span></blockquote><div><br></div><div>Yes I agree that it would be a much more drastic move that would make Swift difficult to use for numerics, and I, at least, would not want to go down that road.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
&gt; Yet I cannot help but think that the rejected alternative may be<br>
&gt; advantageous in one key aspect. `FloatingPoint` comparison is in a<br>
&gt; sense &quot;less refined&quot; (not exactly precise language, I know) than the<br>
&gt; level 2 ordering proposed here, at least in the sense that the latter<br>
&gt; offers more semantic guarantees about the relationships between<br>
&gt; comparison operators.<br>
<br>
</span>No, they are effectively refinement siblings.  If it was a hierarchical<br>
relationship, we could just make the floating point types conform to<br>
Equatable.  But floating point types are *required* by IEEE to have<br>
comparison semantics that conflict with Equatable.<br>
<span class=""><br>
&gt; It&#39;s weird that the less refined `FloatingPoint` refines the more<br>
&gt; refined `Comparable`,<br>
<br>
</span>Do you want to be able to sort floating point numbers without providing<br>
a comparison predicate (one that has to be spelled less obviously than<br>
&quot;&lt;&quot;)?  If so, floating point numbers must be Comparable.  If not, we<br>
could talk about breaking this refinement relationship.<br>
<span class=""><br>
&gt; and I think the acrobatics with compiler support illustrate how the<br>
&gt; design is actively working against Swift&#39;s overarching direction.<br>
<br>
</span>It&#39;s not more acrobatic than things we already do in the standard<br>
library to ensure that people transparently see the right behavior (see<br>
.lazy), and we could probably even find ways to do it without language<br>
features.  It would be less principled, harder to understand, and more<br>
fragile than designing a language feature that addresses the need<br>
directly.</blockquote></div><br></div><div class="gmail_extra">I have an incipient idea. It begins with:</div><div class="gmail_extra"><br></div><div class="gmail_extra">enum ComparisonResult {</div><div class="gmail_extra">  case orderedAscending, orderedSame, orderedDescending, unordered</div><div class="gmail_extra">}</div><div class="gmail_extra"><br></div><div class="gmail_extra">I am sure there is something I am missing which makes this design a horrible idea, but I&#39;m interested in hearing them.</div><div class="gmail_extra"><br></div></div>