April 15, 2008
I agree that's tricky, but isn't it infact true that opEquals is defined as a multimethod?

It appears to be, please follow this link: http://codepad.org/z09oUtB4

So maybe you would just like it to return bool, as opposed to int?  Or maybe it needs better documentation?

Cheers,
	Scott S. McCoy

On Tue, 2008-04-15 at 07:49 +0100, Janice Caron wrote:
> 
> As you know, in existing D, opEquals(), at least for classes, is defined to take an Object parameter, not a C parameter, so even ignoring the inheritance rules, allowing opEquals to compare against multiple types is tricky. You end up writing code like
> 
>     int opEquals(Object o)
>     {
>         A a = cast(A)o;
>         B b = cast(B)o;
>         C c = cast(C)o;
> 
>         if (c !is null)
>         {
>             ...
>         }
>         else if (b !is null)
>         {
>             ...
>         }
>         else if (a !is null)
>         {
>             ...
>         }
>     }
> 
> which is not ideal
> 

April 15, 2008
Sorry, this link :-P

http://codepad.org/wxG1AKBe

On Tue, 2008-04-15 at 02:42 -0700, Scott S. McCoy wrote:
> I agree that's tricky, but isn't it infact true that opEquals is defined as a multimethod?
> 
> It appears to be, please follow this link: http://codepad.org/z09oUtB4
> 
> So maybe you would just like it to return bool, as opposed to int?  Or maybe it needs better documentation?
> 
> Cheers,
> 	Scott S. McCoy
> 
> On Tue, 2008-04-15 at 07:49 +0100, Janice Caron wrote:
> > 
> > As you know, in existing D, opEquals(), at least for classes, is defined to take an Object parameter, not a C parameter, so even ignoring the inheritance rules, allowing opEquals to compare against multiple types is tricky. You end up writing code like
> > 
> >     int opEquals(Object o)
> >     {
> >         A a = cast(A)o;
> >         B b = cast(B)o;
> >         C c = cast(C)o;
> > 
> >         if (c !is null)
> >         {
> >             ...
> >         }
> >         else if (b !is null)
> >         {
> >             ...
> >         }
> >         else if (a !is null)
> >         {
> >             ...
> >         }
> >     }
> > 
> > which is not ideal
> > 
> 

April 15, 2008
On 15/04/2008, Scott S. McCoy <tag@cpan.org> wrote:
> I agree that's tricky, but isn't it infact true that opEquals is defined
>  as a multimethod?
>
>  It appears to be, please follow ...
>  http://codepad.org/wxG1AKBe

But that won't work if you compile with -w, because then you have to use the override keyword, which in turn insists that opEquals have the same signature as in Object.


>  So maybe you would just like it to return bool, as opposed to int?

No. That is, of /course/ I want it to return bool, but I don't /just/ want it to return bool. This proposal is all about ditching inheritance and replacing it with a compiler-generated default implementation, which results in very different (but, in my opinion, correct) behavior for comparisons.

If all you want is for opEquals to return bool, there is a different thread for that discussion.
April 15, 2008
Janice Caron wrote:
> On 15/04/2008, Bruce Adams <tortoise_74@yeah.who.co.uk> wrote:
> 
>> I don't think even this is safe. The normal definition of inheritance is
> 
> Well, that's kindof the point. is(==) wouldn't /use/ inheritance. It
> wouldn't be inheritable. It's just like constructors aren't
> inheritable.
> 
> The whole point is the recognition that inheritance is not the right
> mechanism when it comes to comparisons, and hence the quest for a
> different mechanism that /is/ appropriate.

Well, that depends. If I design a class hierarchy where I want to compare instances, I'd either have the superclass define the comparison, if it's appropriate. If, OTOH, the different subclasses should compare differently, then of course the comparison has to be defined for them separately. I'm not sure I see a big problem here.

>> Yes. The semantics are there. We just need to find a syntax that
>> fits better with D. This doesn't quite sit right when everything
>> else is an Op-something.
> 
> It wouldn't be a function in the conventional sense. Choosing a syntax
> that makes it look /not/ like a function is entirely deliberate. It's
> just like constructors don't look like functions; destructors don't
> look like functions; class invariants don't look like functions; unit
> tests don't look like functions.
> 
> opAdd() is a function, subject to all the normal rules of functions,
> including inheritance, overloading, overriding, etc. They're different
> beasts, so they need to look different, syntactically.
> 
> (Also, I chose "is" so as to avoid introducing a new keyword).
April 15, 2008
Janice Caron wrote:
> As you know, in existing D, opEquals(), at least for classes, is
> defined to take an Object parameter, not a C parameter, so even
> ignoring the inheritance rules, allowing opEquals to compare against
> multiple types is tricky. You end up writing code like
> 
>     int opEquals(Object o)
>     {
>         A a = cast(A)o;
>         B b = cast(B)o;
>         C c = cast(C)o;
> 
>         if (c !is null)
>         {
>             ...
>         }
>         else if (b !is null)
>         {
>             ...
>         }
>         else if (a !is null)
>         {
>             ...
>         }
>     }
> 
> which is not ideal

Ok, but bear with me here for a moment. Suppose you need to write specific code for comparisons between A, B, and C. You'd have to tell the compiler somehow which of your code lines are for which comparison, right?

And the above is not very much typing. And it seems flexible and clear enough. Now, changing the syntax would add yet another thing for the compiler to think about, and, if it doesn't bring at least the same clarity plus some significant enhancement to productivity, clarity, ease of use, or something else, then what's the use.

So, maybe I'm missing the real point here?
April 15, 2008
On 15/04/2008, Georg Wrede <georg@nospam.org> wrote:
>  Well, that depends. If I design a class hierarchy where I want to compare
> instances, I'd either have the superclass define the comparison, if it's
> appropriate. If, OTOH, the different subclasses should compare differently,
> then of course the comparison has to be defined for them separately. I'm not
> sure I see a big problem here.

The only thing that would be different is the *default* behavior, by which I mean the behavior of a subclass which does not explicitly provide its own equality comparison.

Under the inheritance mechanism, the default comparison function returns true iff super.opEquals(Object other) returned true.

Under the is(==) mechanism, the default comparison function would
return true iff all of the following conditions are simultaneously
met: (1) the lhs and rhs were of the same type, (2) lhs.super compares
equal to rhs.super, and (3) all member variables of lhs compare equal
to corresponding member variables of rhs.

So, if you subclass A to get B, but don't add any new member variables, then the default comparison test would be the same. But if you add new member variables, then those would get included, by default, in the new test.

But again, I'm only talking about /default/ behavior here. If you don't want default behavior, you can override, and get any behavior you want.
April 15, 2008
On 15/04/2008, Georg Wrede <georg@nospam.org> wrote:
> and, if it doesn't bring at least the same clarity
> plus some significant enhancement to productivity, clarity, ease of use, or
> something else, then what's the use.
>
>  So, maybe I'm missing the real point here?

How about, it brings significant enhancement to productivity, clarity, and ease of use?

I think perhaps you need to re-read the entire thread, since the only way I can really answer that is by repeating things I've already said.
April 15, 2008
After reading the documentation for operator overloading I think there
is a much simpler solution to this problem. have a look at the
definition of Object in phobos - it contains opEquals and opCmp and
that's it. No other opSomthing are defined there.

So basically, I propose just removing those two operators from Object.

if opEquals is not defined for the specific object than the compiler should default to identity comparison (as if you've used "is"), otherwise it'll use the defined method and return bool.

if opCmp is not defined than the compiler will issue an error for trying to compare incomparable types.  otherwise, let it work the same as today.

-- Yigal
April 15, 2008
On Tue, 15 Apr 2008 10:07:31 +0100, Janice Caron <caron800@googlemail.com> wrote:

> On 15/04/2008, Bruce Adams <tortoise_74@yeah.who.co.uk> wrote:
>>  I don't think even this is safe. The normal definition of inheritance is
>
> Well, that's kindof the point. is(==) wouldn't /use/ inheritance. It
> wouldn't be inheritable. It's just like constructors aren't
> inheritable.
>
> The whole point is the recognition that inheritance is not the right
> mechanism when it comes to comparisons, and hence the quest for a
> different mechanism that /is/ appropriate.
>
You misunderstand me. I believe that the operation should be undefined
rather than providing a stub that returns false. As the presence of even a stub
function here is misleading.

class A;
class B: A;
class C: A;

B == C   // should not compile - unless user defined

>
>>  Yes. The semantics are there. We just need to find a syntax that fits
>> better with D.
>>  This doesn't quite sit right when everything else is an Op-something.
>
> It wouldn't be a function in the conventional sense. Choosing a syntax
> that makes it look /not/ like a function is entirely deliberate. It's
> just like constructors don't look like functions; destructors don't
> look like functions; class invariants don't look like functions; unit
> tests don't look like functions.
>
> opAdd() is a function, subject to all the normal rules of functions,
> including inheritance, overloading, overriding, etc. They're different
> beasts, so they need to look different, syntactically.
>
> (Also, I chose "is" so as to avoid introducing a new keyword).

I disagree here. Constructors and destructors are special kinds of function
but they are still functions. The difference is that some special semantics
are apply in addition to normal functional behaviour.
Operators are syntactic sugar to map symbols to functions.
The function is a fundermental unit and one which everyone understands.
Attempting to mask or hide that is counter intuitive.

Regards,

Bruce.
April 16, 2008
On Tue, 15 Apr 2008 10:42:49 +0100, Scott S. McCoy <tag@cpan.org> wrote:

> I agree that's tricky, but isn't it infact true that opEquals is defined
> as a multimethod?
>
Actually this is one of the key insights.
Does D have a good standard solution to the multiple dispatch problem?
I haven't seen it myself but then I haven't been looking.