On Tue, Oct 31, 2017 at 5:56 PM, David Sweeris <daveswee...@mac.com> wrote:
> > On Oct 31, 2017, at 09:07, Stephen Canon via swift-dev < > swift-dev@swift.org> wrote: > > [Replying to the thread as a whole] > > There have been a bunch of suggestions for variants of `==` that either > trap on NaN or return `Bool?`. I think that these suggestions result from > people getting tunnel-vision on the idea of “make FloatingPoint equality > satisfy desired axioms of Equatable / Comparable”. This is misguided. Our > goal is (should be) to make a language usable by developers; satisfying > axioms is only useful in as much as they serve that goal. > > Trapping or returning `Bool?` does not make it easier to write correct > concrete code, and it does not enable writing generic algorithms that > operate on Comparable or Equatable. Those are the problems to be solved. > > Why do they not help write correct concrete code? The overwhelming > majority of cases in which IEEE 754 semantics lead to bugs are due to > non-reflexivity of equality, so let’s focus on that. In the cases where > this causes a bug, the user has code that looks like this: > > // Programmer fails to consider NaN behavior. > if a == b { > } > > but the correct implementation would be: > > // Programmer has thought about how to handle NaN here. > if a == b || (a.isNaN && b.isNaN) { > } > > W.r.t ease of writing correct *concrete* code, the task is to make *this* > specific case cleaner and more intuitive. What does this look like under > other proposed notions of equality? Suppose we make comparisons with NaN > trap: > > // Programmer fails to consider NaN behavior. This now traps if a or b > is NaN. > // That’s somewhat safer, but almost surely not the desired behavior. > if a == b { > } > > // Programmer considers NaNs. They now cannot use `==` until they rule > out > // either a or b is NaN. This actually makes the code *more* > complicated and > // less readable. Alternatively, they use `&==` or whatever we call the > unsafe > // comparison and it’s just like what we had before, except now they > have a > // “weird operator”. > if (!a.isNaN && !b.isNaN && a == b) || (a.isNaN && b.isNaN) { > } > > Now what happens if we return Bool? > > // Programmer fails to consider NaN behavior. Maybe the error when they > // wrote a == b clues them in that they should. Otherwise they just > throw in > // a `!` and move on. They have the same bug they had before. > if (a == b)! { > } > > // Programmer considers NaNs. Unchanged from what we have currently, > // except that we replace || with ??. > if a == b ?? (a.isNaN && b.isNaN) { > } > > If we are going to do the work of introducing another notion of > floating-point equality, it should directly solve non-reflexivity of > equality *by making equality reflexive*. My preferred approach would be to > simply identify all NaNs: > > // Programmer fails to consider NaN behavior. Now their code works! > if a == b { > } > > // Programmer thinks about NaNs, realizes they can simplify their > existing code: > if a == b { > } > > What are the downsides of this? > > (a) it will confuse sometimes experts who expect IEEE 754 semantics. > (b) any code that uses `a != a` as an idiom for detecting NaNs will be > broken. > > (b) is by far the bigger risk. It *will* result in some bugs. Hopefully > less than result from people failing to consider NaNs. The only real risk > with (a) is that we get a biennial rant posted to hacker news about Swift > equality being broken, and the response is basically “read the docs, use > &== if you want that behavior”. > > > One more thought — and it’s crazy enough that I’m not even sure it’s worth > posting — does Swift’s `Equatable` semantics require that `(a == b) != (a > != b)` *always* evaluate to `true`? > Yes. `!=` is an extension method that cannot be overridden, guaranteed to return false if `==` returns true. > Because it seems like the arguments for having `.nan == .nan` return > `false` would apply for `!=` as well. Without getting into trapping, > faulting or returning a `Bool?` / `Maybe` / `Tern`, I can’t think of > anything else that’d get a developer’s attention faster than the same value > being both not equal and not not equal to itself. > > I mean, is that likely to cause any more bugs than having `.nan == .nan` > return `true`? > > I *think* yes, but I tend to use `.isNaN`, so I’m not sure. > > - Dave Sweeris >
_______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev