[swift-dev] Rationalizing FloatingPoint conformance to Equatable

Xiaodi Wu xiaodi.wu at gmail.com
Thu Oct 26 11:40:29 CDT 2017


On Thu, Oct 26, 2017 at 11:38 AM, Jonathan Hull <jhull at gbis.com> wrote:

>
> On Oct 26, 2017, at 9:34 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
> On Thu, Oct 26, 2017 at 10:57 AM, Jonathan Hull <jhull at gbis.com> wrote:
>
>>
>> On Oct 26, 2017, at 8:19 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>
>>
>> On Thu, Oct 26, 2017 at 07:52 Jonathan Hull <jhull at gbis.com> wrote:
>>
>>> On Oct 25, 2017, at 11:22 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>
>>> On Wed, Oct 25, 2017 at 11:46 PM, Jonathan Hull <jhull at gbis.com> wrote:
>>>
>>>> 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.
>>>>
>>>> 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 ‘&==‘.
>>>>
>>>
>>> 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.
>>>
>>>
>>> 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.
>>>
>>>
>>> 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.
>>>>
>>>
>>> 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.
>>>
>>>
>>>
>>> #1 from my previous email (shown again here):
>>>
>>> Currently, I think we should do 3 things:
>>>>>
>>>>> 1) Create a new protocol with a partial equivalence relation with
>>>>> signature of (T, T)->Bool? and automatically conform Equatable things to it
>>>>> 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)
>>>>> 3) Provide an '&==‘ relation on Float, etc… (without a protocol) with
>>>>> the native Float IEEE comparison
>>>>
>>>>
>>> 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.
>>>
>>
>> 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.
>>
>>
>> Correct.  I view this as a good thing, because another way of saying that
>> is: “it makes possible cases where == sometimes conforms to the rules of
>> Equatable and sometimes doesn’t."  Under the solution I am advocating,
>> Numeric would instead allow generic use of '==?’.
>>
>> I suppose an argument could be made that we should extend ‘&==‘ to
>> Numeric from FloatingPoint, but then we would end up with the Rust
>> situation you were talking about earlier…
>>
>
> This would break any `Numeric` algorithms that currently use `==`
> correctly. There are useful guarantees that are common to integer `==` and
> IEEE floating-point `==`; namely, they each model equivalence of their
> respective types at roughly what IEEE calls "level 1" (as numbers, rather
> than as their representation or encoding). Breaking that utterly
> eviscerates `Numeric`.
>
>
> Nope.  They would continue to work as they always have, but would have a
> depreciation warning on them.  The authors of those algorithms would have a
> full depreciation cycle to update the algorithms.  Fixits would be provided
> to make conversion easier.
>

After the depreciation cycle, Numeric would no longer guarantee a common
"level 1" comparison for conforming types.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20171026/b3596f14/attachment.html>


More information about the swift-dev mailing list