A fresh look at comparisons

Janice Caron caron800 at googlemail.com
Mon Apr 14 23:49:21 PDT 2008


On 15/04/2008, Scott S. McCoy <tag at cpan.org> wrote:
> But you're making assumptions about the application's definition of
> equality.

I was, and I got that part wrong, so I retract that part of the idea. See below.


>  See, that's the point of having opEquals overloadable:

I get that now. So what you're basically saying is that

    is(this == c)

isn't enough, because it makes the presumption that typeof(c) /must/
be the same as typeof(this). Whereas, we really need to allow the
programmer to overload for different types.

Still, only a minor change to my proposal would be needed to
accomodate this. We only need to allow the test to be overloaded, so:

    is(this == c) /* standard test */
    is(this == C c) /* overload for type C */


>  Can you say definitively and for certain that in all
>  environments in all programs ever written in D, that an object of type A
>  and an object of type B will never be equal even though they have no
>  common ancestor?

No, so obviously you're right, and we would need to make it
overloadable, as per the above example.


>  And also, we cannot say that for instance, if you have types B and C
>  which are both descendants of type A, that you will want B to be equal
>  to C if A.opEquals() returns true for the two instances.

You're right, and that's one thing I don't like about opEquals, and
which is(==) would solve. So, under the revised proposal:

    class A
    {
        is(this == c) {...}
    }

    class B : A {}
    class C : A {}

    B b;
    C c;

    if (b == c) ...

This test would now have to return false always, because the new rules
must compare B with B, or C with C, and must /not/ cast b and c to
their common type. Under the new rules, to compare B with C, the
programmer would now have to write

    class B : A
    {
        is(this == C c) {...}
    }

    class C : A
    {
        is(this == B b) {...}
    }

I think that covers all the edge cases that people have pointed out.
With that adjustment, the scheme, I think, now works a treat.

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



More information about the Digitalmars-d mailing list