> On Apr 18, 2017, at 8:40 AM, Ben Cohen via swift-evolution 
> <[email protected]> wrote:
> 
>> 
>> On Apr 17, 2017, at 9:40 PM, Chris Lattner via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> 
>>> On Apr 17, 2017, at 9:07 AM, Joe Groff via swift-evolution 
>>> <[email protected] <mailto:[email protected]>> wrote:
>>> 
>>> 
>>>> On Apr 15, 2017, at 9:49 PM, Xiaodi Wu via swift-evolution 
>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>> 
>>>> For example, I expect `XCTAssertEqual<T : FloatingPoint>(_:_:)` to be 
>>>> vended as part of XCTest, in order to make sure that 
>>>> `XCTAssertEqual(resultOfComputation, Double.nan)` always fails.
>>> 
>>> Unit tests strike me as an example of where you really *don't* want level 1 
>>> comparison semantics. If I'm testing the output of an FP operation, I want 
>>> to be able to test that it produces nan when I expect it to, or that it 
>>> produces the right zero.
>> 
>> I find it very concerning that == will have different results based on 
>> concrete vs generic type parameters.  This can only lead to significant 
>> confusion down the road.  I’m highly concerned about situations where taking 
>> a concrete algorithm and generalizing it (with generics) will change its 
>> behavior.
>> 
> 
> It is already the case that you can start with a concrete algorithm, 
> generalize it, and get confusing results – just with a different starting 
> point. If you start with a concrete algorithm on Int, then generalize it to 
> all Equatable types, then your algorithm will have unexpected behavior for 
> floats, because these standard library types fail to follow the rules 
> explicitly laid out for conforming to Equatable. 
> 
> This is bad. Developers need to be able to rely on those rules. The standard 
> library certainly does:
> 
> let a: [Double] = [(0/0)]
> var b = a
> 
> // true, because fast path buffer pointer comparison:
> a == b
> 
> b.reserveCapacity(10) // force a reallocation
> 
> // now false, because memberwise comparison and nan != nan,
> // violating the reflexivity requirement of Equatable:
> a == b 
> 
> 
> Maybe we could go through and special-case all the places in the standard 
> library that rely on this, accounting for the floating point behavior 
> (possibly reducing performance as a result). But we shouldn't expect users to.
> 
> This is a bump in the rug – push it down in one place, it pops up in another. 
> I feel like this proposal at least moves the bump to where fewer people will 
> trip over it. I think it highly likely that the intersection of developers 
> who understand enough about floating point to write truly correct concrete 
> code, but won’t know about or discover the documented difference in generic 
> code, is far smaller than the set of people who hit problems with the 
> existing behavior.
> 
>  A more comprehensive solution, with additional protocols or overloads, 
> representation of unordered comparison etc, might be able to flatten the rug 
> completely, but probably at the cost of introducing complexity that could act 
> as a barrier to entry into the world of writing generic code.

Seems to me that the core of the issue is that the IEEE spec enforces the 
observation that  `==` is usually the wrong question to ask from a mathematical 
PoV when it comes to infinities and NaNs, but we don’t have anything better to 
put in its place when we want to ask it anyway from a less rigorous PoV.

What about having `==` return the layman’s answers, and `===` return IEEE's 
answer? That way the behavior is the same regardless of generic vs concrete. Or 
the other way around, since `===` means “equivalent” / “identical” (I forget 
which), which at least to me implies a stronger similarity than just “equals" 
(plus, this way wouldn’t be source-breaking). Either way, either behavior is 
readily available. And either way, since none of the stdlib numeric types have 
reference semantics, we can have them all follow the same pattern WRT “==“ and 
“===“. For the integer types, the two operators would be interchangeable, but 
it’d allow for generic numeric code that could rely on both operators being 
present.

- Dave Sweeris
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to