July 25, 2014 Re: WAT: opCmp and opEquals woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 7/25/2014 2:55 PM, Jonathan M Davis wrote:
> Doesn't the compiler-generated opEquals do a memcmp when it can?
Yes.
|
July 25, 2014 Re: WAT: opCmp and opEquals woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On 7/25/2014 2:44 PM, H. S. Teoh via Digitalmars-d wrote:
> Uncommenting the const in opCmp fixes the problem. WAT?
opCmp must be const in order to be recognized for TypeInfo.
|
July 25, 2014 Re: WAT: opCmp and opEquals woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 7/25/2014 3:31 PM, Walter Bright wrote: > On 7/25/2014 2:44 PM, H. S. Teoh via Digitalmars-d wrote: >> Uncommenting the const in opCmp fixes the problem. WAT? > > opCmp must be const in order to be recognized for TypeInfo. > See https://dlang.org/operatoroverloading#compare |
July 25, 2014 Re: WAT: opCmp and opEquals woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On 7/25/2014 2:57 PM, Jonathan M Davis wrote:
> Well, that was the case in 2.065, whereas 2.066 currently gives an error if you
> use a type as a key in an AA without defining opEquals for it. That change needs
> to be reverted.
Do you remember which PR it was?
|
July 25, 2014 Re: WAT: opCmp and opEquals woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On 7/25/2014 1:47 PM, H. S. Teoh via Digitalmars-d wrote: > On Fri, Jul 25, 2014 at 06:56:40PM +0000, Jonathan M Davis via Digitalmars-d wrote: > [...] >> So, if we remove the new check for a user-defined opEquals when opCmp >> is defined, then you don't have to define opEquals. > > This is even worse, since it may silently introduce runtime breakage. > The original type may have had opCmp defined just so it can be used with > AA's, and now after the upgrade to 2.066, suddenly the custom opCmp code > they wrote specifically to work with AA's doesn't get used anymore, yet > the compiler silently accepts the code, and the problem won't be found > until runtime. Once again, "The thing is, either this suffers from == behaving differently than AAs, or you've made opEquals superfluous by defining it to be opCmp==0. The latter is a mistake, as Andrei has pointed out, as opCmp may not have a concept of equality, and opEquals may not have a concept of ordering. I.e. it's not just about AAs." What you're defending is code of this sort running without error: S[T] aa; S s; aa[t] = s; assert(s != aa[t]); > Which IMO fits the D motto of being correct first, and performant if you > ask for it. See the above snippet. |
July 25, 2014 Re: WAT: opCmp and opEquals woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Friday, 25 July 2014 at 22:34:41 UTC, Walter Bright wrote: > On 7/25/2014 2:57 PM, Jonathan M Davis wrote: >> Well, that was the case in 2.065, whereas 2.066 currently gives an error if you >> use a type as a key in an AA without defining opEquals for it. That change needs >> to be reverted. > > Do you remember which PR it was? No idea, unfortunately. The only reason that I even know about it is this thread and https://issues.dlang.org/show_bug.cgi?id=13179 (which discusses basically the same thing as this thread). - Jonathan M Davis |
July 25, 2014 Re: WAT: opCmp and opEquals woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On Fri, Jul 25, 2014 at 03:33:24PM -0700, Walter Bright via Digitalmars-d wrote: > On 7/25/2014 3:31 PM, Walter Bright wrote: > >On 7/25/2014 2:44 PM, H. S. Teoh via Digitalmars-d wrote: > >>Uncommenting the const in opCmp fixes the problem. WAT? > > > >opCmp must be const in order to be recognized for TypeInfo. > > > > See https://dlang.org/operatoroverloading#compare That page doesn't say anything about TypeInfo, though. But even then, why doesn't the compiler reject opCmp signatures that don't match the compiler's expectations? T -- It's amazing how careful choice of punctuation can leave you hanging: |
July 25, 2014 Re: WAT: opCmp and opEquals woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On 7/25/2014 4:28 PM, H. S. Teoh via Digitalmars-d wrote: > That page doesn't say anything about TypeInfo, though. It says to follow the form. > But even then, > why doesn't the compiler reject opCmp signatures that don't match the > compiler's expectations? Because you may want to use an opCmp for other purposes. |
July 26, 2014 Re: WAT: opCmp and opEquals woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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
|
July 26, 2014 Re: WAT: opCmp and opEquals woes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright Attachments:
| On 26 July 2014 06:38, Walter Bright via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
> On 7/25/2014 4:10 AM, Regan Heath wrote:
>
>> Sure, Andrei makes a valid point .. for a minority of cases. The
>> majority case
>> will be that opEquals and opCmp==0 will agree. In those minority cases
>> where
>> they are intended to disagree the user will have intentionally defined
>> both, to
>> be different. I cannot think of any case where a user will intend for
>> these to
>> be different, then not define both to ensure it.
>>
>
> You've agreed with my point, then, that autogenerating opEquals as memberwise equality (not opCmp==0) if one is not supplied will be correct unless the user code is already broken.
>
No, because there's no obvious reason to define opEquals if you do define opCmp, and the opEq
|
Copyright © 1999-2021 by the D Language Foundation