WAT: opCmp and opEquals woes

Andrei Alexandrescu via Digitalmars-d digitalmars-d at puremagic.com
Fri Jul 25 18:44:36 PDT 2014


On 7/23/14, 9:45 AM, H. S. Teoh via Digitalmars-d wrote:
> This morning, I discovered this major WAT in D:
>
> ----
> struct S {
>          int x;
>          int y;
>          int opCmp(S s) {
>                  return x - s.x; // compare only x
>          }
> }
>
> void main() {
>          auto s1 = S(1,2);
>          auto s2 = S(1,3);
>          auto s3 = S(2,1);
>
>          assert(s1 < s3); // OK
>          assert(s2 < s3); // OK
>          assert(s3 > s1); // OK
>          assert(s3 > s2); // OK
>          assert(s1 <= s2 && s2 >= s1); // OK
>          assert(s1 == s2); // FAIL -- WAT??
> }
> ----
>
> The reason for this is that the <, <=, >=, > operators are defined in
> terms of opCmp (which, btw, is defined to return 0 when the objects
> being compared are equal), but == is defined in terms of opEquals. When
> opEquals is not defined, it defaults to the built-in compiler
> definition, which is a membership equality test, even if opCmp *is*
> defined, and returns 0 when the objects are equal.
>
> Why isn't "a==b" rewritten as "a.opCmp(b)==0"?? I'm pretty sure TDPL
> says this is the case (unfortunately I'm at work so I can't check my
> copy of TDPL).
>
> https://issues.dlang.org/show_bug.cgi?id=13179
>
> :-(

Getting back to the root of it: I don't think this is a WAT.

Types may choose to define lax ordering comparisons, such as 
case-insensitive ordering for sorting purposes. Such comparisons create 
large equivalence classes. Deeming two objects equal, on the other hand, 
must be quite a bit more stringent.

A WAT would be defining ordering comparison to be case insensitive and 
then finding stuff in a hashtable that wasn't put there.

Clearly for common arithmetic types, !(a < b) && !(b < a) is the same as 
a == b. However, that's not the case for a variety of types and 
orderings. The one relationship between the two operators would be that 
if a == b then !(a < b) && !(b < a).

I think we should remove the breakage introduced by requiring opEquals 
if opCmp is defined. It breaks good code for no good reason.


Andrei




More information about the Digitalmars-d mailing list