<div dir="ltr">On Wed, Apr 26, 2017 at 6:23 PM, Michel Fortin <span dir="ltr">&lt;<a href="mailto:michel.fortin@michelf.ca" target="_blank">michel.fortin@michelf.ca</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"><div style="word-wrap:break-word"><div><div class="h5"><div><blockquote type="cite"><div>Le 26 avr. 2017 à 18:33, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt; a écrit :</div><br class="m_-7516674379154606521Apple-interchange-newline"><div><div dir="ltr">On Wed, Apr 26, 2017 at 2:14 PM, Michel Fortin 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:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Just throwing a idea that came to me while reading this discussion (hopefully not duplicating something that was already suggested)...<br>
<br>
We could introduce `FiniteFloat` and `FiniteDouble` types that would disallow NaN and infinity. Computations creating NaN or infinity would trap with these types, mimicking what happens with integers in Swift. Converting a `Double` to `FiniteDouble` would be achieved through a `finiteValue` property like this:<br>
<br>
        var a = 1.0<br>
        var b = a.finiteValue!<br>
<br>
where the `finiteValue` property returns a `FiniteDouble?` that is `nil` for NaN or infinity values. The finite type variant can conform to Equatable with no issue. The regular one that allows NaNs and infinity would then have less pressure to conform to Equatable. Just request the finite value whenever you need it:<br>
<br>
        dict[a.finiteValue!] = &quot;a&quot;<br>
<br>
I understand that this goes a bit beyond solving the problem with comparison which is caused by NaNs and not by infinity values. But it&#39;s quite easy to explain what &quot;finite&quot; means and it follows how integers works. It also has the interesting property of guarantying a finite value for APIs that needs that, which I believe is more frequent than APIs that require only a non-NaN value. Hence why I&#39;m suggesting FiniteDouble and not NonNaNDouble.<br></blockquote><div><br></div><div>The issue, here, again is that you&#39;re proposing tinkering with Swift floating point types without addressing the motivations here, which is an issue with _Comparable_. The problem is that:</div><div><br></div><div>(a) People use arrays of type Float and Double.</div><div><br></div><div>(b) You can invent new ways to represent floating point values, but as long as you interact with data from anywhere else (not just interoperating with C or using existing algorithms that make use of floating point types, but even simply reading in any file that stores floating point data, since those will be serialized as IEEE floating point values), you _will_ be using Float and Double.</div><div><br></div><div>(c) People expect to sort and compare arrays of type Float and Double.</div><div><br></div><div>You can introduce a type called DefinitelyNotNaNDouble and then rename Double to PotentiallyReallyBadNaNDouble, but people will still need to sort and compare arrays of PotentiallyReallyBadNaNDouble. And after all that work, you still have not answered the question, how do we write generic algorithms that (a) use generic comparison; and (b) behave in a sensible way when working with values of type PotentiallyReallyBadNaNDouble?</div></div></div></div>
</div></blockquote><br></div></div></div><div>You are right. I had the dictionary/set problem in mind, but that&#39;s not the one related to `Comparable`. With this design the problem with `Comparable` would have to be &quot;solved&quot; by making `Double` (the one that supports NaN) not conform to `Comparable`. Which means that the basic generic `sort` would not work with a `[Double]`; instead we&#39;d have to write a more specialized `sort` for that...</div><div><br></div><div>And to write that more specialized `sort` we add a `SometimeComparable` protocol with the ability to tell when values are unordered and have `Float` and `Double` conform to it. We could probably make `Comparable` conform to it automatically. And with that the `sort` for `SometimeComparable` can also handle the plain `Comparable` and thus becomes the most generic one. In the end we have two comparable protocols, one for when things are always comparable and one for when they are only sometime comparable, and generic algorithms would be free to accept one or the other depending on whether they can deal with the unordered case or not.</div><div><br></div><div>(We could do the same thing with `Equatable` vs. `SometimeEquatable`. Generic algorithms would have to choose one or the other in their generic constraints.)</div></div></blockquote><div><br></div><div>Right, and this is the solution that Rust uses, but as pointed out in the proposal here, it&#39;s been found that this is not a good solution. So, the goal here is a single Equatable and Comparable protocol to which Float and Double conform. Again, the goal is to be able to write generic `sort` with `Double`; we want to make it work correctly, not remove it altogether.</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>Maybe I&#39;m turning in full circle here. There&#39;s actually no need for `FixedDouble` with this, except maybe as a convenience wrapper type to pass a double to a generic algorithm that can&#39;t deal with unordered values.</div><span class=""><div><br></div><div>
<div style="color:rgb(0,0,0);letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;word-wrap:break-word"><div style="color:rgb(0,0,0);letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;word-wrap:break-word"><div style="color:rgb(0,0,0);letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;word-wrap:break-word"><div style="color:rgb(0,0,0);font-family:Helvetica;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;word-wrap:break-word"><span class="m_-7516674379154606521Apple-style-span" style="border-collapse:separate;font-variant-ligatures:normal;font-variant-east-asian:normal;line-height:normal;border-spacing:0px"><div style="word-wrap:break-word"><span class="m_-7516674379154606521Apple-style-span" style="border-collapse:separate;color:rgb(0,0,0);font-family:Helvetica;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;border-spacing:0px"><div style="word-wrap:break-word"><span class="m_-7516674379154606521Apple-style-span" style="border-collapse:separate;color:rgb(0,0,0);font-family:Helvetica;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:normal;text-align:-webkit-auto;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;border-spacing:0px"><div style="word-wrap:break-word">-- <br>Michel Fortin</div><div style="word-wrap:break-word"><span style="text-align:-webkit-auto"><a href="https://michelf.ca" target="_blank">https://michelf.ca</a></span></div></span></div></span></div></span></div></div></div></div>
</div>
<br></span></div></blockquote></div><br></div></div>