<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">Alternatively, we could introduce a new type `PotentiallyUnknown` that’s kind of like `Optional` but has different equality semantics. We’d probably also need to introduce a `PartiallyEquatable` (probably the wrong word) protocol too though. I don’t think this is really that feasible.</div><div class=""><br class=""></div><div class=""><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco;" class=""><span style="color: #c900a4" class="">protocol</span> PartiallyEquatable {</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco;" class=""> <span style="color: #c800a4" class="">static</span> <span style="color: #c900a4" class="">func</span> ==(lhs: <span style="color: #c800a4" class="">Self</span>, rhs: <span style="color: #c800a4" class="">Self</span>) <span style="color: #c800a4" class="">-></span> <span style="color: #790ead" class="">Bool</span>?</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco;" class="">}</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; min-height: 17px;" class=""><br class=""></div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco;" class=""><span style="color: #c900a4" class="">enum</span> PotentiallyUnknown<span style="color: #c800a4" class=""><</span>T: PartiallyEquatable<span style="color: #c800a4" class="">></span> {</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco;" class=""> <span style="color: #c800a4" class="">case</span> known(T)</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco;" class=""> <span style="color: #c800a4" class="">case</span> unknown(T)</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco;" class="">}</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco; min-height: 17px;" class=""><br class=""></div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco;" class=""><span style="color: #c900a4" class="">extension</span> PotentiallyUnknown: PartiallyEquatable when T: PartiallyEquatable {</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco;" class=""> <span style="color: #c800a4" class="">static</span> <span style="color: #c900a4" class="">func</span> ==(lhs: PotentiallyUnknown, rhs: PotentiallyUnknown) <span style="color: #c800a4" class="">-></span> <span style="color: #790ead" class="">Bool</span>? {</div><div style="margin: 0px 0px 0px 94.6px; text-indent: -94.7px; line-height: normal; font-family: Monaco;" class=""> <span style="color: #c800a4" class="">guard</span> <span style="color: #c800a4" class="">case</span> <span style="color: #c800a4" class="">.</span>known(<span style="color: #c900a4" class="">let</span> l) <span style="color: #c800a4" class="">=</span> lhs, <span style="color: #c800a4" class="">case</span> <span style="color: #c800a4" class="">.</span>known(<span style="color: #c900a4" class="">let</span> r) <span style="color: #c800a4" class="">=</span> rhs <span style="color: #c800a4" class="">else</span> {</div><div style="margin: 0px 0px 0px 126.1px; text-indent: -126.2px; line-height: normal; font-family: Monaco;" class=""> <span style="color: #c800a4" class="">return</span> <span style="color: #c800a4" class="">nil</span></div><div style="margin: 0px 0px 0px 94.6px; text-indent: -94.7px; line-height: normal; font-family: Monaco;" class=""> }</div><div style="margin: 0px 0px 0px 94.6px; text-indent: -94.7px; line-height: normal; font-family: Monaco;" class=""> <span style="color: #c800a4" class="">return</span> l <span style="color: #c800a4" class="">==</span> r</div><div style="margin: 0px 0px 0px 63px; text-indent: -63.1px; line-height: normal; font-family: Monaco;" class=""> }</div><div style="margin: 0px 0px 0px 31.5px; text-indent: -31.6px; line-height: normal; font-family: Monaco;" class="">}</div></div><div class=""><br class=""></div><div class="">I think it’s a novel idea, but I don’t think it would work great in practice.</div><br class=""><div><blockquote type="cite" class=""><div class="">On Apr 25, 2017, at 6:38 PM, Jonathan Hull via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Apr 25, 2017, at 5:25 PM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" class="">xiaodi.wu@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">On Tue, Apr 25, 2017 at 6:53 PM, Jonathan Hull <span dir="ltr" class=""><<a href="mailto:jhull@gbis.com" target="_blank" class="">jhull@gbis.com</a>></span> wrote:<br class=""></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" class="">I just wanted to ask for more detail on why this is a non-starter (it seems like most of my ideas are dismissed as “non-starters”, but I am rarely given a detailed reason why).<div class=""><br class=""></div><div class="">Migration would be a renaming from ‘Double' to ‘Double?’, but it wouldn’t be cosmetic. It would free us to use a non-optional Double, where we can guarantee the answer wouldn’t be NaN/nil. We would, as you say, have functions like ‘cos(Double?)->Double?’ which propagate the optional, but we could also add a ‘cos(Double)->Double’ overload which guarantees an actual result. For something like Tan, we would only have the optional version because the answer may actually be undefined, even when the input isn't.</div></div></blockquote><div class=""><br class=""></div><div class="">Leave aside how one might implement such a system for a moment. The first major issue is that your idea does not address the issues we're talking about here:</div><div class=""><br class=""></div><div class="">We are debating, for instance, how to compare arrays with elements of type `Double`. In your design, the question remains how we would compare arrays with elements of type `Double?`. If the answer is that you cannot compare arrays of type `[Double?]`, then we have a problem, because that's the type that people will use when they ingest data that might contain NaN. Sure, they can unwrap each element before using their data, but they can also test each element with `isNaN` today. We are trying to *improve* on the user experience of comparing arrays of floating point values *without* checking if they contain NaN, not trying to take that feature away.</div></div></div></div></div></blockquote><div class=""><br class=""></div><div class=""><div class="">It solves the main problem we are dealing with in Comparable because defining Comparable on non-optional Double (without possibility of NaN) is fairly simple.</div></div><div class=""><br class=""></div><div class="">You could compare an array of ‘Double?' in the same way you could compare an array of ‘Int?’ now. It would work the same way optionals work everywhere else.</div><div class=""><br class=""></div><div class="">You would just test for a lack of numerical result by checking the optional in the usual Swift way: guard let, if let, etc...</div><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">Your design also doesn't address the problem of how NaN should compare with NaN. Only now, you've pushed the problem to `Optional`. By design, every `Optional<T>.none` compares equal to every other `Optional<U>.none` (yes, even of different types).</div></div></div></div></div></blockquote><div class="">Yes, the one major difference in behavior, which I mentioned in my earlier email, is that we are replacing NaN != NaN with nil == nil. Everything else should behave the same. The part that saves us here, is that Swift forces you to explicitly consider the optional case.</div><br class=""><div class="">Basically, I am taking the spirit/intent of the law over the letter of it. As far as I can tell, (quiet) NaN was originally designed to provide the functionality which we use optional for in Swift. The NaN != NaN thing came out of limitations of the computers in the 1980’s because you needed a way to tell if something was NaN or not (and isNaN() didn’t exist yet).</div><div class=""><br class=""></div><div class="">The programmer (mental) model would be that Swift Double just doesn’t have NaN, and anywhere where you would normally return NaN, you return nil instead. However, the property of using NaN’s bits to represent nil let’s us inter-op seamlessly with C and ObjC (or any other language’s) code. They just treat it as a double with NaN as normal (including NaN != NaN) and we interface with it as ‘Double?'</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""> This did not always work correctly, if I recall, but it does now and it's an intentional part of the design. However, NaN must compare not equal to every NaN. These could not be more different properties. It seems quite absurd on its face that we might want NaN to compare equal to a value of type `Optional<UIViewController>`.<br class=""></div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">Is there an algorithm that requires NaN != NaN that couldn’t be reasonably rewritten to handle nil/optionals instead? </div><div class=""><br class=""></div><div class="">I haven’t been able to think of one. They are extremely similar, because they were designed for the same use-cases. The examples you have given so far (e.g. cos(Double)->Double) would all be trivial to migrate.</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Jon</div><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><br class=""></div><div class=""><br class=""></div><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" class=""><div class="">In short, it would actually make people consider conditions which result in NaN because of Swift’s machinery which makes people consider nil.</div><div class=""><br class=""></div><div class="">It also allows non-optional Double to easily conform to Comparable, and removes the gotchas around Collections… Pretty big wins for a “cosmetic rename”. The only thing we lose is 'NaN != Nan' (because nil == nil), but then algorithms that had relied on that would be forced to consider the NaN/nil case explicitly because of the optionals.</div><div class=""><br class=""></div><div class="">It would also inter-op well with C/ObjC code by just having the compiler overlay Double? for Double…</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Jon</div><div class=""><br class=""></div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Apr 16, 2017, at 11:44 AM, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" target="_blank" class="">xiaodi.wu@gmail.com</a>> wrote:</div><br class="gmail-m_-2105822621181210603gmail-m_6947921313014429943Apple-interchange-newline"><div class=""><div dir="ltr" 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" class="">On Sun, Apr 16, 2017 at 1:14 PM, Jonathan Hull<span class="gmail-m_-2105822621181210603gmail-m_6947921313014429943Apple-converted-space"> </span><span dir="ltr" class=""><<a href="mailto:jhull@gbis.com" target="_blank" class="">jhull@gbis.com</a>></span><span class="gmail-m_-2105822621181210603gmail-m_6947921313014429943Apple-converted-space"> </span>wrote:<br class=""><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" class=""><span class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Apr 16, 2017, at 10:42 AM, Xiaodi Wu via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>> wrote:</div><br class="gmail-m_-2105822621181210603gmail-m_6947921313014429943m_5034690051034842618Apple-interchange-newline"><div class=""><span 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;float:none;display:inline" class="">The point is that, when you manipulate two real numbers, sometimes there is no numeric result. You cannot simply wish this away with a new numeric type because it is not an artifact of _modeling_ real numbers but rather intrinsic to mathematics itself.</span></div></blockquote></div><br class=""></span><div class="">I agree with the rest of what you said, but I have to disagree on this point. What I think he is saying is that, in Swift, we really should be representing the NaN case as an optional instead of a magic value on the type itself (similar to how swift uses an optional instead of NSNotFound).</div><div class=""><br class=""></div><div class="">In fact, that might be an actual option here. For ‘Double?’ the compiler could use the bit pattern for NaN internally to represent .none (I believe it does similar tricks to save space with other optional types). Then disallow reference to NaN within swift code. Functions or operations which could produce NaN would either have to produce an optional or trap in case of NaN. (e.g. the trig functions would likely return an optional, and 0/0 would trap).</div><div class=""><br class=""></div><div class="">I think it would actually lead to much better code because the compiler would force you to have to explicitly deal with the case of optional/NaN when it is possible. Migration would be tricky though...</div></div></blockquote><div class=""><br class=""></div><div class="">This is essentially a cosmetic renaming from `Double` to `Double?`. There are rules for propagating NaN which numeric algorithms expect. For example, `cos(.nan)` returns a value. If your design is to work, every function that takes a `Double` will need to take a `Double?`.</div><div class=""><br class=""></div><div class="">Just as Swift String conforms to Unicode standards, FloatingPoint conforms to IEEE standards. You'd have to come up with enormous benefits to justify breaking that. Doing so for Swift 4 is plainly a non-starter.</div><div class=""><br class=""></div><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" class=""><div class=""></div><div class="">Thanks,</div><div class="">Jon</div></div></blockquote></div></div></div></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div></div>
</div></blockquote></div><br class=""></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>