> On 18 Apr 2017, at 19:06, David Sweeris via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> 
>> On Apr 18, 2017, at 8:40 AM, Ben Cohen via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>>> 
>>> On Apr 17, 2017, at 9:40 PM, Chris Lattner via swift-evolution 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> 
>>>> On Apr 17, 2017, at 9:07 AM, Joe Groff via swift-evolution 
>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>>> 
>>>> 
>>>>> On Apr 15, 2017, at 9:49 PM, Xiaodi Wu via swift-evolution 
>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution


If Xiaodi is correct and we can actually fit floats to standard-library 
Comparable and Equatable without unacceptable tradeoffs (again, not an FP 
expert, can’t judge how often NaNs actually come up), that’s obviously optimal. 
If we can’t, I think we need to keep the standard library clear and give 
FloatingPoints two implementations of Comparable - one according to IEEE754, 
which can be the default conformance, and another which conforms to the 
standard library semantics of what “Comparable” and “Equatable” operators 
should do.

If this was any other similar problem, I couldn’t think of a better solution. 
Zero run-time cost, clear semantics which prevent unexpected behaviour. Unlike 
the contextual approach, which chooses for you some semantics which you may not 
want, you would always have the option of explicitly saying which type of 
comparison you want for FloatingPoints.

Users will often expect a Float to compare to another Float the same way an Int 
compares to another Int. The truth is that floating-points just aren’t 
trivially comparable or equatable, because of things like .NaN never equalling 
another .NaN. Again, not an expert, but my intuition is that rather than try to 
hide the complexity, or wish it away by trapping, maybe we should embrace it 
and just provide a good API to work with multiple interpretations of 
Comparable/Equatable when it comes to FloatingPoints.


- Karl

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to