> On Oct 31, 2017, at 7:26 PM, Xiaodi Wu <xiaodi...@gmail.com> wrote:
> 
> On Tue, Oct 31, 2017 at 5:56 PM, David Sweeris <daveswee...@mac.com 
> <mailto:daveswee...@mac.com>> wrote:
> 
> On Oct 31, 2017, at 09:07, Stephen Canon via swift-dev <swift-dev@swift.org 
> <mailto: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

Wait, what? So if I have a `Password` type, and want to trigger extra logging 
if the `!=` function is called too many times within a second or something, 
that won't get called in generic code? That seems... unintuitive...

- Dave Sweeris
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Reply via email to