View mode: basic / threaded / horizontal-split · Log in · Help
April 14, 2005
Object.opCmp - about time we came to a decision
It's about time we finally made up our mind what we're going to do with 
Object.opCmp.

Three possible solutions I can see:

1. Get rid of it, and either reimplement AAs and sort using templates, 
or implement the alternative solution described in point 3 here:

http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/10558

Just thinking about it, is this solution really implementable, 
considering the possibility of inheriting multiple opCmp methods (from a 
class and an interface or from multiple interfaces)?

2. Leave the current DMD behaviour in, and document it properly. 
Something to the effect of this:

----------
arrays.html - Associative arrays

For associative arrays to work on a class KeyType, the class must 
override the following member functions of Object:

	int opEquals(Object)
	int opCmp(Object)
	uint toHash()

Note that the first two must have the parameter of type Object, not of 
the specific class in which they are defined.


arrays.html - Array properties

For sorting to work on a class type, the class must override the int 
opCmp(Object) member of class Object.  Note that the parameter type is 
Object, not the specific class in which it is defined.


operatoroverloading.html - Overloading == and !=

The equality operator of a class must be defined by overriding 
Object.opEquals(Object) (not by merely creating a new opEquals of a more 
specific parameter type), otherwise associative arrays will not work 
correctly.


operatoroverloading.html - Overloading <, <=, > and >= - Rationale

The existence of Object.opCmp(Object) is due to a constraint of the way 
associative arrays and sorting are implemented.  As such, the comparator 
must be defined by overriding this method (not by merely creating a new 
opCmp of a more specific parameter type), otherwise associative arrays 
and sorting will not work correctly.

----------

3. Keep Object.opCmp, but redefine it to always return zero.  So 
effectively all objects of a class rank equally unless they override 
opCmp to specify otherwise.  Consequently a principle of OO is 
effectively maintained - in a derived class, one can choose to add a 
natural ordering, rather than being expected to subtract the meaningless 
(and contrary to GC guidelines) natural ordering from Object.  And AAs 
will at least work on classes of which the designer has defined opEquals 
and toHash but not opCmp.

Indeed, something will need to be done to the documentation whichever 
route we take.

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on 
the 'group where everyone may benefit.
April 14, 2005
Re: Object.opCmp - about time we came to a decision
It's got to go.

Score an emphatic 1 for option 1.

"Stewart Gordon" <smjg_1998@yahoo.com> wrote in message news:d3m7do$1bdk$1@digitaldaemon.com...
> It's about time we finally made up our mind what we're going to do with Object.opCmp.
>
> Three possible solutions I can see:
>
> 1. Get rid of it, and either reimplement AAs and sort using templates, or implement the alternative solution described 
> in point 3 here:
>
> http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/10558
>
> Just thinking about it, is this solution really implementable, considering the possibility of inheriting multiple 
> opCmp methods (from a class and an interface or from multiple interfaces)?
>
> 2. Leave the current DMD behaviour in, and document it properly. Something to the effect of this:
>
> ----------
> arrays.html - Associative arrays
>
> For associative arrays to work on a class KeyType, the class must override the following member functions of Object:
>
> int opEquals(Object)
> int opCmp(Object)
> uint toHash()
>
> Note that the first two must have the parameter of type Object, not of the specific class in which they are defined.
>
>
> arrays.html - Array properties
>
> For sorting to work on a class type, the class must override the int opCmp(Object) member of class Object.  Note that 
> the parameter type is Object, not the specific class in which it is defined.
>
>
> operatoroverloading.html - Overloading == and !=
>
> The equality operator of a class must be defined by overriding Object.opEquals(Object) (not by merely creating a new 
> opEquals of a more specific parameter type), otherwise associative arrays will not work correctly.
>
>
> operatoroverloading.html - Overloading <, <=, > and >= - Rationale
>
> The existence of Object.opCmp(Object) is due to a constraint of the way associative arrays and sorting are 
> implemented.  As such, the comparator must be defined by overriding this method (not by merely creating a new opCmp of 
> a more specific parameter type), otherwise associative arrays and sorting will not work correctly.
>
> ----------
>
> 3. Keep Object.opCmp, but redefine it to always return zero.  So effectively all objects of a class rank equally 
> unless they override opCmp to specify otherwise.  Consequently a principle of OO is effectively maintained - in a 
> derived class, one can choose to add a natural ordering, rather than being expected to subtract the meaningless (and 
> contrary to GC guidelines) natural ordering from Object.  And AAs will at least work on classes of which the designer 
> has defined opEquals and toHash but not opCmp.
>
> Indeed, something will need to be done to the documentation whichever route we take.
>
> Stewart.
>
> -- 
> My e-mail is valid but not my primary mailbox.  Please keep replies on the 'group where everyone may benefit.
April 14, 2005
Re: Object.opCmp - about time we came to a decision
In article <d3m7do$1bdk$1@digitaldaemon.com>, Stewart Gordon says...
>
>2. Leave the current DMD behaviour in, and document it properly. 

This solution gets my vote.  IMO, there is nothing odd about requiring the
implementor provide comparison and equality operators when they really want
their class to behave like a value type in the first place (ie. sortable).  

There is also a precedent for object collections in C#, by requiring the
IComparable interface, which requires the "compareTo(Object)" method.  Java also
has the Comparable interface which happens to be identical.  So I think we're on
the right track by keeping things as-is.

Can I request that the behavior for sorting with the default operators be
included as well?  I think that's another potential source for confusion if left
alone.


$0.02

- EricAnderton at yahoo
April 14, 2005
Re: Object.opCmp - about time we came to a decision
"pragma" <pragma_member@pathlink.com> wrote ...
> In article <d3m7do$1bdk$1@digitaldaemon.com>, Stewart Gordon says...
> >
> >2. Leave the current DMD behaviour in, and document it properly.
>
> This solution gets my vote.  IMO, there is nothing odd about requiring the
> implementor provide comparison and equality operators when they really
want
> their class to behave like a value type in the first place (ie. sortable).
>
> There is also a precedent for object collections in C#, by requiring the
> IComparable interface, which requires the "compareTo(Object)" method.
Java also
> has the Comparable interface which happens to be identical.  So I think
we're on
> the right track by keeping things as-is.

Don't get you, Eric. Are you saying keep the broken opCmp() and opEquals()
in Object, and just assume the user will do the right thing by overriding
them in their own class? If so, I have to disagree strongly. Such things
should be trapped as compile-time errors, not runtime oblique-behaviour.

IMO, they should get ripped out of Object, and then be supported via an
Interface or similar. Note that these Object methods were in place long
before Interfaces were even available. That might explain a lot :-)

I believe toHash() is in the same boat?

- Kris
April 14, 2005
Re: Object.opCmp - about time we came to a decision
I vote for fixing it, as I have already outlined.

Post: Re: Solution - Re: How to bridge the gap between user defined types and built in   types?
Date: April 14th, 2005 @ 6:08am (US Central time?)
In response to the thread: How to bridge the gap between user defined types and built in   types?

TZ

"Stewart Gordon" <smjg_1998@yahoo.com> wrote in message news:d3m7do$1bdk$1@digitaldaemon.com...
> It's about time we finally made up our mind what we're going to do with
> Object.opCmp.
>
> Three possible solutions I can see:
>
> 1. Get rid of it, and either reimplement AAs and sort using templates,
> or implement the alternative solution described in point 3 here:
>
> http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/10558
>
> Just thinking about it, is this solution really implementable,
> considering the possibility of inheriting multiple opCmp methods (from a
> class and an interface or from multiple interfaces)?
>
> 2. Leave the current DMD behaviour in, and document it properly.
> Something to the effect of this:
>
> ----------
> arrays.html - Associative arrays
>
> For associative arrays to work on a class KeyType, the class must
> override the following member functions of Object:
>
> int opEquals(Object)
> int opCmp(Object)
> uint toHash()
>
> Note that the first two must have the parameter of type Object, not of
> the specific class in which they are defined.
>
>
> arrays.html - Array properties
>
> For sorting to work on a class type, the class must override the int
> opCmp(Object) member of class Object.  Note that the parameter type is
> Object, not the specific class in which it is defined.
>
>
> operatoroverloading.html - Overloading == and !=
>
> The equality operator of a class must be defined by overriding
> Object.opEquals(Object) (not by merely creating a new opEquals of a more
> specific parameter type), otherwise associative arrays will not work
> correctly.
>
>
> operatoroverloading.html - Overloading <, <=, > and >= - Rationale
>
> The existence of Object.opCmp(Object) is due to a constraint of the way
> associative arrays and sorting are implemented.  As such, the comparator
> must be defined by overriding this method (not by merely creating a new
> opCmp of a more specific parameter type), otherwise associative arrays
> and sorting will not work correctly.
>
> ----------
>
> 3. Keep Object.opCmp, but redefine it to always return zero.  So
> effectively all objects of a class rank equally unless they override
> opCmp to specify otherwise.  Consequently a principle of OO is
> effectively maintained - in a derived class, one can choose to add a
> natural ordering, rather than being expected to subtract the meaningless
> (and contrary to GC guidelines) natural ordering from Object.  And AAs
> will at least work on classes of which the designer has defined opEquals
> and toHash but not opCmp.
>
> Indeed, something will need to be done to the documentation whichever
> route we take.
>
> Stewart.
>
> -- 
> My e-mail is valid but not my primary mailbox.  Please keep replies on
> the 'group where everyone may benefit.
April 15, 2005
Re: Object.opCmp - about time we came to a decision
In article <d3mp8g$1t7a$1@digitaldaemon.com>, Kris says...
>
>
>"pragma" <pragma_member@pathlink.com> wrote ...
>> In article <d3m7do$1bdk$1@digitaldaemon.com>, Stewart Gordon says...
>> >
>> >2. Leave the current DMD behaviour in, and document it properly.
>>
>> This solution gets my vote.  IMO, there is nothing odd about requiring the
>> implementor provide comparison and equality operators when they really
>want
>> their class to behave like a value type in the first place (ie. sortable).
>>
>> There is also a precedent for object collections in C#, by requiring the
>> IComparable interface, which requires the "compareTo(Object)" method.
>Java also
>> has the Comparable interface which happens to be identical.  So I think
>we're on
>> the right track by keeping things as-is.
>
>Don't get you, Eric. Are you saying keep the broken opCmp() and opEquals()
>in Object, and just assume the user will do the right thing by overriding
>them in their own class? If so, I have to disagree strongly. Such things
>should be trapped as compile-time errors, not runtime oblique-behaviour.
>
>IMO, they should get ripped out of Object, and then be supported via an
>Interface or similar. Note that these Object methods were in place long
>before Interfaces were even available. That might explain a lot :-)
>
>I believe toHash() is in the same boat?

I had a huge reply written up, and then I noticed this line from the OP:

>Note that the first two must have the parameter of type Object, not of the specific class in which they are defined.

::cringe:: I forgot about this.

Far be it from me to back an opinion, and continue to ride it when it starts to
fall apart.

So allow me to divorce my ego from my previous post.  I need to give this a
*lot* more thought.  I thought I understood the entire problem, but upon
rereading the thread and related material I'm left with more questions than
answers.  It's also eaten several hours of my time. :(

The short, short answer is that I like the current implementation largely
becuase it hasn't given me much trouble and seems to fit most of the use-cases
out there.  After all, if it isn't broken, don't fix it, right?  But I also
understand that this is pretty much head-in-the-sand thinking so I'm not 100% on
this one.

The biggest quandry I have is: how much of a problem is using the wrong override
for opCmp and opEquals?  Is this really an education problem, or a design
problem?  I honestly don't know. :(

I'll get back to you with a more concrete opinion.  Thank you for prodding me to
think about this Kris.

- EricAnderton at yahoo
April 15, 2005
Re: Object.opCmp - about time we came to a decision
Current definition:

class Object
{
   void print();
   char[] toString();
   uint toHash();
   int opCmp(Object o);
   int opEquals(Object o);
}

Only definition that makes sense to me:

class Object
{
   char[] toString();
}

And that's only because toString() is a benign thing. In principle, 
it should be:

class Object
{
}
April 15, 2005
Re: Object.opCmp - about time we came to a decision
Aye.

Supposing the "Three Stooges" were removed ... do you have a suggestion in
terms of implementation? Are you thinking in terms of Interfaces? For
example:

interface Comparable
{
 int opEquals (Object o);
 int opCmp (Object o);
}

interface Hashable
{
 uint toHash();
}

Or something else instead?

- Kris


"Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message
news:d3n7n3$28d4$1@digitaldaemon.com...
> Current definition:
>
> class Object
> {
>     void print();
>     char[] toString();
>     uint toHash();
>     int opCmp(Object o);
>     int opEquals(Object o);
> }
>
> Only definition that makes sense to me:
>
> class Object
> {
>     char[] toString();
> }
>
> And that's only because toString() is a benign thing. In principle,
> it should be:
>
> class Object
> {
> }
>
>
>
April 15, 2005
Re: Object.opCmp - about time we came to a decision
Well, aren't you keen to open up all Pandora's boxes in one go!

The answer depends on whether we feel that D should be a language 
that follows interface-based runtime polymorphism, or uses generic 
approaches. There's no reason why the language cannot be defined 
such that the compiler will only accept ar.sort() when ar is 
composed of homogeneous built-in types, or instances of class types 
that all share a comon base that has an opCmp() defined. Similarly, 
there's no reason why AAs could not be built only on types that have 
the appropriate methods.

Since this approach also fully supports runtime polymorphic 
approaches, but does not mandate them, I think it's the best 
approach. (Obviously)

Matthew

"Kris" <fu@bar.com> wrote in message 
news:d3nid8$2hqe$1@digitaldaemon.com...
> Aye.
>
> Supposing the "Three Stooges" were removed ... do you have a 
> suggestion in
> terms of implementation? Are you thinking in terms of Interfaces? 
> For
> example:
>
> interface Comparable
> {
>  int opEquals (Object o);
>  int opCmp (Object o);
> }
>
> interface Hashable
> {
>  uint toHash();
> }
>
> Or something else instead?
>
> - Kris
>
>
> "Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message
> news:d3n7n3$28d4$1@digitaldaemon.com...
>> Current definition:
>>
>> class Object
>> {
>>     void print();
>>     char[] toString();
>>     uint toHash();
>>     int opCmp(Object o);
>>     int opEquals(Object o);
>> }
>>
>> Only definition that makes sense to me:
>>
>> class Object
>> {
>>     char[] toString();
>> }
>>
>> And that's only because toString() is a benign thing. In 
>> principle,
>> it should be:
>>
>> class Object
>> {
>> }
>>
>>
>>
>
>
April 15, 2005
Re: Object.opCmp - about time we came to a decision
Just looking for trouble :-)

Supposing the compiler itself did not change ... any other solutions?

- Kris


Matthew wrote:
> Well, aren't you keen to open up all Pandora's boxes in one go!
> 
> The answer depends on whether we feel that D should be a language 
> that follows interface-based runtime polymorphism, or uses generic 
> approaches. There's no reason why the language cannot be defined 
> such that the compiler will only accept ar.sort() when ar is 
> composed of homogeneous built-in types, or instances of class types 
> that all share a comon base that has an opCmp() defined. Similarly, 
> there's no reason why AAs could not be built only on types that have 
> the appropriate methods.
> 
> Since this approach also fully supports runtime polymorphic 
> approaches, but does not mandate them, I think it's the best 
> approach. (Obviously)
> 
> Matthew
> 
> "Kris" <fu@bar.com> wrote in message 
> news:d3nid8$2hqe$1@digitaldaemon.com...
> 
>>Aye.
>>
>>Supposing the "Three Stooges" were removed ... do you have a 
>>suggestion in
>>terms of implementation? Are you thinking in terms of Interfaces? 
>>For
>>example:
>>
>>interface Comparable
>>{
>> int opEquals (Object o);
>> int opCmp (Object o);
>>}
>>
>>interface Hashable
>>{
>> uint toHash();
>>}
>>
>>Or something else instead?
>>
>>- Kris
>>
>>
>>"Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message
>>news:d3n7n3$28d4$1@digitaldaemon.com...
>>
>>>Current definition:
>>>
>>>class Object
>>>{
>>>    void print();
>>>    char[] toString();
>>>    uint toHash();
>>>    int opCmp(Object o);
>>>    int opEquals(Object o);
>>>}
>>>
>>>Only definition that makes sense to me:
>>>
>>>class Object
>>>{
>>>    char[] toString();
>>>}
>>>
>>>And that's only because toString() is a benign thing. In 
>>>principle,
>>>it should be:
>>>
>>>class Object
>>>{
>>>}
>>>
>>>
>>>
>>
>>
> 
>
« First   ‹ Prev
1 2 3 4 5
Top | Discussion index | About this forum | D home