[swift-evolution] [pitch] Comparison Reform

Xiaodi Wu xiaodi.wu at gmail.com
Tue Apr 25 19:25:40 CDT 2017

On Tue, Apr 25, 2017 at 6:53 PM, Jonathan Hull <jhull at gbis.com> wrote:

> 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).
> 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.

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:

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.

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). 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>`.

In short, it would actually make people consider conditions which result in
> NaN because of Swift’s machinery which makes people consider nil.
> 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.
> It would also inter-op well with C/ObjC code by just having the compiler
> overlay Double? for Double…
> Thanks,
> Jon
> On Apr 16, 2017, at 11:44 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
> On Sun, Apr 16, 2017 at 1:14 PM, Jonathan Hull <jhull at gbis.com> wrote:
>> On Apr 16, 2017, at 10:42 AM, Xiaodi Wu via swift-evolution <
>> swift-evolution at swift.org> wrote:
>> 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.
>> 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).
>> 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).
>> 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...
> 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?`.
> 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.
> Thanks,
>> Jon
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170425/130642d6/attachment.html>

More information about the swift-evolution mailing list