> 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
