<div><br><div class="gmail_quote"><div dir="auto">On Thu, Oct 26, 2017 at 07:52 Jonathan Hull <<a href="mailto:jhull@gbis.com">jhull@gbis.com</a>> 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><blockquote type="cite"><div>On Oct 25, 2017, at 11:22 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>> wrote:</div><br class="m_-203124280784081011Apple-interchange-newline"><div><div>On Wed, Oct 25, 2017 at 11:46 PM, Jonathan Hull <span><<a href="mailto:jhull@gbis.com" target="_blank">jhull@gbis.com</a>></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"><div style="word-wrap:break-word">As someone mentioned earlier, we are trying to square a circle here. We can’t have everything at once… we will have to prioritize. I feel like the precedent in Swift is to prioritize safety/correctness with an option ignore safety and regain speed.<div><br></div><div>I think the 3 point solution I proposed is a good compromise that follows that precedent. It does mean that there is, by default, a small performance hit for floats in generic contexts, but in exchange for that, we get increased correctness and safety. This is the exact same tradeoff that Swift makes for optionals! Any speed lost can be regained by providing a specific override for FloatingPoint that uses ‘&==‘.</div></div></blockquote><div><br></div><div>My point is not about performance. My point is that `Numeric.==` must continue to have IEEE floating-point semantics for floating-point types and integer semantics for integer types, or else existing uses of `Numeric.==` will break without any way to fix them. The whole point of *having* `Numeric` is to permit such generic algorithms to be written. But since `Numeric.==` *is* `Equatable.==`, we have a large constraint on how the semantics of `==` can be changed. </div></div></div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>It would also conform to the new protocol and have it’s Equatable conformance depreciated. Once we have conditional conformances, we can add Equatable back conditionally. Also, while we are waiting for that, Numeric can provide overrides of important methods when the conforming type is Equatable or FloatingPoint.</div></div></div><div style="word-wrap:break-word"><div><div><br></div><br><blockquote type="cite"><div><div><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"><div style="word-wrap:break-word"><div>For example, if someone wants to write a generic function that works both on Integer and FloatingPoint, then they would have to use the new protocol which would force them to correctly handle cases involving NaN.</div></div></blockquote><div><br></div><div>What "new protocol" are you referring to, and what do you mean about "correctly handling cases involving NaN"? The existing API of `Numeric` makes it possible to write generic algorithms that accommodate both integer and floating-point types--yes, even if the value is NaN. If you change the definition of `==` or `<`, currently correct generic algorithms that use `Numeric` will start to _incorrectly_ handle NaN.</div></div></div></div></div></blockquote><div><br></div><div><br></div></div></div><div style="word-wrap:break-word"><div><div>#1 from my previous email (shown again here):</div></div></div><div style="word-wrap:break-word"><div><div><blockquote type="cite"><div><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 style="word-wrap:break-word"><div><div><div class="m_-203124280784081011m_-4014199803616980042h5"><div><div><blockquote type="cite"><div><div><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">Currently, I think we should do 3 things:<br><br>1) Create a new protocol with a partial equivalence relation with signature of (T, T)->Bool? and automatically conform Equatable things to it<br>2) Depreciate Float, etc’s… Equatable conformance with a warning that it will eventually be removed (and conform Float, etc… to the partial equivalence protocol)<br>3) Provide an '&==‘ relation on Float, etc… (without a protocol) with the native Float IEEE comparison</blockquote></div></div></div></div></blockquote></div></div></div></div></div></div></blockquote></div></div></div></blockquote></div><div><br></div></div></div><div style="word-wrap:break-word"><div><div>In this case, #2 would also apply to Numeric. You can think of the new protocol as a failable version of Equatable, so in any case where it can’t meet equatable’s rules, it returns nil.</div></div></div></blockquote><div dir="auto"><br></div><div dir="auto">Again, Numeric makes possible the generic use of == with floating-point semantics for floating-point values and integer semantics for integer values; this design would not.</div><div dir="auto"><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><div></div></div></div></blockquote><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><blockquote type="cite"><div><div><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"><div style="word-wrap:break-word"><div>If speed is super important in that particular case, then they can write overrides for the FloatingPoint case which uses &==, and for Equatable which uses ==.</div><div><br></div><div>Because Float’s Equatable conformance is just being depreciated (with a warning/fixit), authors have at least a version to decide whether speed or correctness (or hopefully both) is most important to them.</div></div></blockquote><div><br></div><div>My point here is not about generic algorithms written to take any Equatable value; it's about protocol-based numeric algorithms, which we in SE-0104 devoted much time and energy to support in the first place.</div></div></div></div></div></blockquote><div><br></div></div></div><div style="word-wrap:break-word"><div><div>See above.</div><div><br></div><div>Thanks,</div><div>Jon</div></div></div><div style="word-wrap:break-word"><div><br><blockquote type="cite"><div><div><div class="gmail_extra"><div class="gmail_quote"><div> </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><div>Thanks,</div><div>Jon</div><div><br></div><div>P.S. We really should not be comparing against the speed of algorithms which don’t correctly handle NaN. Let’s compare Apples to Apples.</div></div></div></blockquote><div><br></div><div>Again, what do you mean about "correctly handle NaN"? Most algorithms today *do* correctly handle NaN, in that they are concordant with the IEEE-specified behavior. Set *not* deduplicating NaN *is* correct handling of NaN, for instance, for as long as NaN != NaN.</div><div><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><div><div class="m_-203124280784081011m_-4014199803616980042h5"><div><div><blockquote type="cite"><div>On Oct 25, 2017, at 6:36 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>> wrote:</div><br class="m_-203124280784081011m_-4014199803616980042m_-6282367460427292267Apple-interchange-newline"><div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">On Wed, Oct 25, 2017 at 8:26 PM, Jonathan Hull<span class="m_-203124280784081011m_-4014199803616980042m_-6282367460427292267Apple-converted-space"> </span><span><<a href="mailto:jhull@gbis.com" target="_blank">jhull@gbis.com</a>></span><span class="m_-203124280784081011m_-4014199803616980042m_-6282367460427292267Apple-converted-space"> </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"><span>> On Oct 25, 2017, at 9:01 AM, David Sweeris via swift-dev <<a href="mailto:swift-dev@swift.org" target="_blank">swift-dev@swift.org</a>> wrote:<br>><br>> That said, I fully acknowledge that this is all above my pay grade (also I hadn't realized that the issue was as settled as it apparently is). If splitting the protocols is a no-go from the get go, I'll go back to trying to figure out a better way to handle it without doing that.<br><br><br></span>I don’t think it is settled. The issue that Xiaodi mentioned was a PartiallyEq protocol which still had a signature of (T,T)->Bool. People just used that protocol instead of Equatable without taking into account the difference in behavior. The signature of (T,T)->Bool? changes things because people are forced to deal with the optional.<br><br>Currently, I think we should do 3 things:<br><br>1) Create a new protocol with a partial equivalence relation with signature of (T, T)->Bool? and automatically conform Equatable things to it<br>2) Depreciate Float, etc’s… Equatable conformance with a warning that it will eventually be removed (and conform Float, etc… to the partial equivalence protocol)<br>3) Provide an '&==‘ relation on Float, etc… (without a protocol) with the native Float IEEE comparison<br><br>I think this provides several benefits. #3 allows pure speed when needed, but not in a generic context (and is appropriately scary to cause some thought). #1 forces correct handling in generic contexts. #2 gives people time to make the adjustment, but also eventually requires them to switch to using #1 or #3.<br><br>I think it will cause A LOT of currently incorrect code to be fixed.<br></blockquote><div><br></div><div>One issue which occurred to me only recently, which I hadn't considered, renders my `&==` idea and all similar schemes untenable:</div><div><br></div><div>Useful algorithms can and are written which operate on both floating-point and integer numeric types. In fact, the whole point of laboriously designing `Numeric` as part of SE-0104 was to make it possible to do so. If IEEE comparison is relegated to `FloatingPoint` and the only operator remaining on `Numeric` is `==`, then not only will there be a mandatory performance hit, but currently correct algorithms can be broken with absolutely no way to express a fix.</div></div></div></div></div></blockquote></div><br></div></div></div></div></div></blockquote></div><br></div></div>
</div></blockquote></div></div></blockquote></div></div>