[swift-dev] Rationalizing FloatingPoint conformance to Equatable

Xiaodi Wu xiaodi.wu at gmail.com
Tue Oct 24 21:04:33 CDT 2017

On Tue, Oct 24, 2017 at 4:28 PM, David Zarzycki <dave at znu.io> wrote:

> On Oct 24, 2017, at 14:55, Ben Cohen via swift-dev <swift-dev at swift.org>
> wrote:
> There really is no way to square this circle. Every option is going to
> have downsides. We have to balance correctness, least surprise/most
> expected behavior for most people, and consistency. For me, making generic
> use of Equatable and Comparable stick to the documented conformance
> generically, while keeping FP-specific uses the way they are, is the least
> bad option.
> Hi Ben,
> Out of curiosity, what do you think about breaking Equatable into two
> protocols: Equatable and Substitutable? The former would be defined in
> terms of mathematics, while the latter is simple to define and usable by
> collections, etc. For example, while +0 equals -0, they are not
> substitutable (because 1.0 / +0.0 == +inf BUT 1.0 / -0.0 == -inf). In the
> case of NaNs, substitutability would depend on the NaN payload being the
> same or not (because some later subsystem might interpret the NaN payload).

> Finally, and unless I’m missing something, floating-point
> “substitutability” would translate to bitwise equality at the hardware
> level, which is nice from a performance perspective.

As Steve pointed out, floating-point "substitutability" as you define it is
unlikely to be desired in most contexts; differentiation by NaN payload or
by decimal value representation is highly unintuitive, and it would be
intolerable for generic `.contains(.nan)` to sometimes return true and
sometimes false depending on NaN payload.

> On the topic of sorting, we could do the same thing, where we break
> Comparable into two protocols: Comparable and Sortable. The former would be
> defined in terms of mathematics, while the latter has no mathematical
> obligation and therefore values like +0 and -0 can be consistently sorted.
> The same goes of NaNs with payloads (they can be sorted). And finally, at
> the hardware level, this should be quite efficient because of how the
> floating point bits are laid out (in that an integer comparison of FP bits
> should work for this Sortable proposal).

Floating point values can certainly be consistently sorted as an sequence
of bits, but again, it is unlikely that anyone would want such a sort of
their floating point values.

But as to the topic of splitting protocols, it is essentially the design
adopted by Rust. During discussion of Ben's original proposal, some core
team members argued very eloquently against such a design based on what's
happened in Rust. Namely:

- If Float is not Equatable but instead SomethingOtherThanEquatable (in
Rust, it's called `PartialEq`), then we will have officially done our job
in terms of stdlib semantic guarantees. However, in practice, people *want*
to write generic algorithms that work with both integers and floating point
- Based on the Rust experience, what people will do when they realize that
Float doesn't conform to Equatable is instead to write generic algorithms
that operate on SomethingOtherThanEquatable while assuming that integer
`==` and floating point `==` will work the same way.
- The result is that you now have two protocols instead of one, but most
people still use only one--and still use it incorrectly. The existing
problem has simply been transferred from Equatable to
SomethingOtherThanEquatable. The new Equatable accomplishes nothing in
terms of helping people write better code.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20171024/c479a980/attachment.html>

More information about the swift-dev mailing list