[swift-evolution] [pitch] Comparison Reform

Xiaodi Wu xiaodi.wu at gmail.com
Wed Apr 26 18:32:19 CDT 2017

On Wed, Apr 26, 2017 at 6:23 PM, Michel Fortin <michel.fortin at michelf.ca>

> Le 26 avr. 2017 à 18:33, Xiaodi Wu <xiaodi.wu at gmail.com> a écrit :
> On Wed, Apr 26, 2017 at 2:14 PM, Michel Fortin via swift-evolution <
> swift-evolution at swift.org> wrote:
>> Just throwing a idea that came to me while reading this discussion
>> (hopefully not duplicating something that was already suggested)...
>> 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:
>>         var a = 1.0
>>         var b = a.finiteValue!
>> 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:
>>         dict[a.finiteValue!] = "a"
>> 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's
>> quite easy to explain what "finite" 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'm suggesting FiniteDouble and not
>> NonNaNDouble.
> The issue, here, again is that you're proposing tinkering with Swift
> floating point types without addressing the motivations here, which is an
> issue with _Comparable_. The problem is that:
> (a) People use arrays of type Float and Double.
> (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.
> (c) People expect to sort and compare arrays of type Float and Double.
> 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?
> You are right. I had the dictionary/set problem in mind, but that's not
> the one related to `Comparable`. With this design the problem with
> `Comparable` would have to be "solved" 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'd have to write
> a more specialized `sort` for that...
> 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.
> (We could do the same thing with `Equatable` vs. `SometimeEquatable`.
> Generic algorithms would have to choose one or the other in their generic
> constraints.)

Right, and this is the solution that Rust uses, but as pointed out in the
proposal here, it'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.

Maybe I'm turning in full circle here. There'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't deal with unordered values.
> --
> Michel Fortin
> https://michelf.ca
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170426/9ae08371/attachment.html>

More information about the swift-evolution mailing list