On Apr 22, 2017, at 6:06 PM, Xiaodi Wu <[email protected]> wrote:
> but my quick reaction to `&==` is that it would make me quite nervous to have 
> `==` not bound to 754-equals as it is in essentially every other language. In 
> particular, I worry about the risk of people porting numerical code that 
> depends on isnan(x) <—> !(x < y) in non-obvious ways that they are unlikely 
> to test. I’ll try to follow up with more detailed thoughts tomorrow.
> 
> Indeed, it makes me a little nervous too. That said, `==` being either bound 
> or not bound to 754 depending on the context is what makes me even more 
> nervous.
> 
> I was once adamantly against a new spelling for `==`, but on reconsideration 
> it's clear to me that few if any numerical recipes can be ported verbatim 
> from C-like languages and we should probably not encourage people to do so. 
> Already, `+` needs to be rewritten as `&+`, `<<` probably should be rewritten 
> as `&<<` (I still haven't had enough time to think about this), and the 
> bitwise operators have differing precedences that require careful 
> proofreading.


I haven’t been following this proposal or discussion closely, but it seems to 
me that there are a few workable approaches with different tradeoffs:

1. The strictly correct but user hostile approach:

* == and != are tied to the Equatable protocol, which is essentially the == 
operation.
* <, <=, >, >= are tied to the Comparable protocol, which is essentially the 
<=> operation.
* Hashable doesn’t require equatable, it requires a related StrictlyEquatable 
protocol.
* StrictlyEquatable refines Equatable (with no other requirements, it is just a 
marker protocol), in which case FP types can’t conform to it, and thus can’t 
participate as dictionary keys

=> This approach sucks because you can’t have Set<Float>, or Dictionary<Float, 
String>.

2. The strictly correct but somewhat user hostile approach:

* == and != are tied to the Equatable protocol, which is essentially the == 
operation.
* <, <=, >, >= are tied to the Comparable protocol, which is essentially the 
<=> operation.
* Hashable doesn’t require equatable, it requires a related StrictlyEquatable 
protocol.
* StrictlyEquatable doesn’t refine Equatable: it has a different requirement, 
and FP types can therefore implement both Equatable and StrictlyEquatable.

=> This approach is suboptimal because implementing your own type requires you 
to implement the <=> operation, as well as the StrictlyEquatable protocol, both.

3. The user friendly but incorrect model:

* == and != are tied to the Equatable protocol, which is essentially the == 
operation.
* <, <=, >, >= are tied to the Comparable protocol, which is essentially the 
<=> operation.
* Hashable is defined in terms of Equatable.

=> This is easy (types just have to define <=>), but fails for FP types.


I don’t think that this proposal is acceptable as written.  I think it is 
really bad that abstracting a concrete algorithm would change its behavior so 
substantially.  I don’t care about SNaNs, but I do care about the difference 
between +0/-1 and secondarily that of NaN handling.  It seems really bad that 
generalizing something like:

func doThing(a : Double, b : Double) -> Bool {
   ….
   return a != b
}

to:

func doThing<T : FloatingPoint> (a : T, b : T) -> Bool {
   ….
   return a != b
}

would change behavior (e.g. when a is -0.0 and b is +0.0).   Likewise, "T : 
Equatable".

-Chris


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

Reply via email to