> On Apr 18, 2017, at 11:43 AM, Stephen Canon via swift-evolution 
> <[email protected]> wrote:
>> On Apr 18, 2017, at 11:40 AM, Ben Cohen via swift-evolution 
>> <[email protected] <mailto:[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.
> 
> For what it’s worth, I agree with Ben and Joe; there are some surprises 
> lurking here, but they are less hazardous to the inexperienced programmer 
> than the surprises that lurk with any other solution I’ve seen.

Agreed.

John.

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

Reply via email to