www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Object.opCmp - about time we came to a decision

reply Stewart Gordon <smjg_1998 yahoo.com> writes:
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:

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.
Apr 14 2005
next sibling parent "Matthew" <admin.hat stlsoft.dot.org> writes:
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:

 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. 

Apr 14 2005
prev sibling next sibling parent reply pragma <pragma_member pathlink.com> writes:
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
Apr 14 2005
next sibling parent reply "Kris" <fu bar.com> writes:
"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

 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.

 has the Comparable interface which happens to be identical.  So I think

 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
Apr 14 2005
next sibling parent pragma <pragma_member pathlink.com> writes:
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

 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.

 has the Comparable interface which happens to be identical.  So I think

 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
Apr 14 2005
prev sibling parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Kris" <fu bar.com> wrote in message news:d3mp8g$1t7a$1 digitaldaemon.com...
 "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


 implementor provide comparison and equality operators when they really

 their class to behave like a value type in the first place (ie.


 There is also a precedent for object collections in C#, by requiring the
 IComparable interface, which requires the "compareTo(Object)" method.

 has the Comparable interface which happens to be identical.  So I think

 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 :-)

Well i agree with you 100%. I always thought we should get rid of them and make them compile-time errors. I really hope people/Walter listen to you!
 I believe toHash() is in the same boat?

 - Kris

Apr 15 2005
prev sibling next sibling parent "Uwe Salomon" <post uwesalomon.de> writes:
 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).

?? I thought the question was about Object.opCmp() to get rid of, not of opCmp() itself? Implementing an opCmp() for your own class is still possible with solution #1, but only these will have an opCmp() then. This said, i vote for #1. Ciao uwe
Apr 14 2005
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
pragma wrote:
<snip>
 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.

Actually, Java 1.5 (aka Java™ 2 Platform Standard Edition 5.0 for some reason I can't imagine) has Comparable as a template, such that compareTo [sic] is defined only on the scope of the comparability.
 So I think we're on the right track by keeping things as-is.

Why do some people seem to think copying others just for the sake of it is the way to go? Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Apr 15 2005
parent reply xs0 <xs0 xs0.com> writes:
Stewart Gordon wrote:
 pragma wrote:
 <snip>
 
 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.

<snip> Actually, Java 1.5 (aka Java™ 2 Platform Standard Edition 5.0 for some reason I can't imagine) has Comparable as a template, such that compareTo [sic] is defined only on the scope of the comparability.

Actually, Java 1.5 doesn't have templates, but generics.. The Comparable interface is always the same, you can just specify some class when you type, so you don't have to cast as much (just in the source code, that is, after it gets compiled, I believe the result is the same no matter what you type). Basically, Comparable<T> always compiles as Comparable<Object>...
 So I think we're on the right track by keeping things as-is.

Why do some people seem to think copying others just for the sake of it is the way to go?

Wouldn't know :) I'd leave things as is, but redefine int opCmp(Object o) { if (this is o) return 0; throw new SomeException("You need to define opCmp(Object) for " ~ o.classinfo.name); } uint opHash(Object o) { return 0; } After/if/when introspection is added, these two can easily use it to do something more meaningful (for example, find all opCmp functions and choose one based on types, and hash and xor all the fields, respectively) xs0
Apr 15 2005
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
xs0 wrote:
<snip>
 I'd leave things as is, but redefine
 
 int opCmp(Object o)
 {
     if (this is o)

Why not if (this == o) so that if one has defined opEquals, it'll get the message?
         return 0;
 
     throw new SomeException("You need to define opCmp(Object) for " ~ 
 o.classinfo.name);
 }

Why should applications tell their users to define opCmp(Object)? Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Apr 15 2005
next sibling parent reply xs0 <xs0 xs0.com> writes:
Stewart Gordon wrote:
 xs0 wrote:
 <snip>
 
 I'd leave things as is, but redefine

 int opCmp(Object o)
 {
     if (this is o)

Why not if (this == o) so that if one has defined opEquals, it'll get the message?

I don't know, really. Could be as well, considering that the default opEquals is the same thing anyway. OTOH, it's not that important. Who will compare only equal objects anyway?
 
         return 0;

     throw new SomeException("You need to define opCmp(Object) for " ~ 
 o.classinfo.name);
 }

<snip> Why should applications tell their users to define opCmp(Object)?

Well, what I said and "comparison not defined for type Blah" are about equally useful to the users (not at all), yet my message is useful at least to coders? And if you just say it's not defined, everybody will come filing bugs about how their opCmp(Blah) actually is defined :) xs0
Apr 15 2005
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
xs0 wrote:
 Stewart Gordon wrote:

 Why should applications tell their users to define opCmp(Object)?

Well, what I said and "comparison not defined for type Blah" are about equally useful to the users (not at all), yet my message is useful at least to coders? And if you just say it's not defined, everybody will come filing bugs about how their opCmp(Blah) actually is defined :)

The whole point of exception messages is to be addressed to the user. Almost any exception message is bound to find its way into production code one day. And so the "You need to" notation truly is blaming the user for a fault of the programmer. On the other hand, simply saying "comparison not defined for type Blah" or similar, while equally meaningless to the user, doesn't label anyone as at fault, and arguably looks more like indication of a bug than a bogus message of action required from the user. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Apr 18 2005
parent xs0 <xs0 xs0.com> writes:
Stewart Gordon wrote:
 xs0 wrote:
 
 Stewart Gordon wrote:

<snip>
 Why should applications tell their users to define opCmp(Object)?

Well, what I said and "comparison not defined for type Blah" are about equally useful to the users (not at all), yet my message is useful at least to coders? And if you just say it's not defined, everybody will come filing bugs about how their opCmp(Blah) actually is defined :)

The whole point of exception messages is to be addressed to the user. Almost any exception message is bound to find its way into production code one day. And so the "You need to" notation truly is blaming the user for a fault of the programmer. On the other hand, simply saying "comparison not defined for type Blah" or similar, while equally meaningless to the user, doesn't label anyone as at fault, and arguably looks more like indication of a bug than a bogus message of action required from the user.

If the user ever sees a message from opCmp(), the app is totally not ready for use, I mean, it's such a basic thing. So, I was kind of assuming that the user would never see such a message, but the developer will. In any case, the point wasn't the exact wording. It can easily be personless. xs0
Apr 18 2005
prev sibling parent reply xs0 <xs0 xs0.com> writes:
BTW, after some thinking, opEquals should do the same; you don't know 
whether something is equal or not (unless it is identity-equal), so you 
can't just say it isn't.

To sum up, I believe these should be the default implementations:

int opCmp(Object o)
{
// basically doesn't work, but explains what should be done
     if (this==o) return 0;
     if (this.classinfo==o.classinfo) {
         throw new SomeException("You need to define opCmp(Object) for 
"~o.classinfo.name);
     } else {
         throw new SomeException("You need to define opCmp(Object) in " 
~ this.classinfo.name ~ " that can compare with " ~ o.classinfo.name);
     }
}

int opEquals(Object o)
{
// basically doesn't work, but explains what should be done
     if (this is o) return 1;
     if (this.classinfo==o.classinfo) {
         throw new SomeException("You need to define opEquals(Object) 
for "~o.classinfo.name);
     } else {
         throw new SomeException("You need to define opEquals(Object) in 
  " ~ this.classinfo.name ~ " that can test for equality with " ~ 
o.classinfo.name);
     }
}

uint toHash()
{
// basically works, but is utterly bad; still, if you compile properly
// it will tell you there is a problem
     version(RUNTIME_LINT) {
         throw new PerformanceException("The default toHash() method is 
being used for class " ~ this.classinfo.name ~". It could not be more 
inefficient, so you should implement a better one.");
     }
     return 0;
}


xs0

Stewart Gordon wrote:
 xs0 wrote:
 <snip>
 
 I'd leave things as is, but redefine

 int opCmp(Object o)
 {
     if (this is o)

Why not if (this == o) so that if one has defined opEquals, it'll get the message?
         return 0;

     throw new SomeException("You need to define opCmp(Object) for " ~ 
 o.classinfo.name);
 }

<snip> Why should applications tell their users to define opCmp(Object)? Stewart.

Apr 15 2005
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
xs0 wrote:
 BTW, after some thinking, opEquals should do the same; you don't know 
 whether something is equal or not (unless it is identity-equal), so you 
 can't just say it isn't.

To me, not defining an opEquals is basically stating that two object references are equal only by referring to one and the same object.
 To sum up, I believe these should be the default implementations:
 
 int opCmp(Object o)
 {
 // basically doesn't work, but explains what should be done
     if (this==o) return 0;
     if (this.classinfo==o.classinfo) {
         throw new SomeException("You need to define opCmp(Object) for 
 "~o.classinfo.name);
     } else {
         throw new SomeException("You need to define opCmp(Object) in " ~ 
 this.classinfo.name ~ " that can compare with " ~ o.classinfo.name);
     }
 }

I still don't get what practical use this idea really has. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Apr 18 2005
parent reply xs0 <xs0 xs0.com> writes:
Stewart Gordon wrote:
 xs0 wrote:
 
 BTW, after some thinking, opEquals should do the same; you don't know 
 whether something is equal or not (unless it is identity-equal), so 
 you can't just say it isn't.

To me, not defining an opEquals is basically stating that two object references are equal only by referring to one and the same object.

To me, not defining an opEquals is basically stating you won't compare objects with ==. IMHO, if you want to compare references, you have is, and if you're writing templates that use ==, you should define opEquals anyway.
 To sum up, I believe these should be the default implementations:

 int opCmp(Object o)
 {
 // basically doesn't work, but explains what should be done
     if (this==o) return 0;
     if (this.classinfo==o.classinfo) {
         throw new SomeException("You need to define opCmp(Object) for 
 "~o.classinfo.name);
     } else {
         throw new SomeException("You need to define opCmp(Object) in " 
 ~ this.classinfo.name ~ " that can compare with " ~ o.classinfo.name);
     }
 }

<snip top of upside-down reply> I still don't get what practical use this idea really has.

Well, I thought that one of the major issues with opCmp and the like is that they're defined in Object, which provides a problematic default implementation, that currently compares based on their objects addresses in memory, which is horrible. The other issue people had is that they define Foo.opCmp(Foo) and it doesn't work. I was trying to address those two issues by having Object still contain those methods (which is imho good) yet have them work in a GC-safe way, while not assuming any ordering/equalness at all, and if they do throw an exception, it might as well be something useful to the coder, which obviously thought that his code was going to be called, but it didn't. xs0
Apr 18 2005
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
xs0 wrote:
<snip>
 To me, not defining an opEquals is basically stating you won't compare 
 objects with ==. IMHO, if you want to compare references, you have is, 
 and if you're writing templates that use ==, you should define opEquals 
 anyway.

And if I want to use a template from someone else's library wrote with a class from someone else's library...? Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Apr 18 2005
parent xs0 <xs0 xs0.com> writes:
Stewart Gordon wrote:
 xs0 wrote:
 <snip>
 
 To me, not defining an opEquals is basically stating you won't compare 
 objects with ==. IMHO, if you want to compare references, you have is, 
 and if you're writing templates that use ==, you should define 
 opEquals anyway.

<snip> And if I want to use a template from someone else's library wrote with a class from someone else's library...? Stewart.

Well, I'm sure that argument can be used for any given implementation of opEquals.. Nothing will fit all possible requirements.. I don't know, extend the class and implement opEquals, or, if its a hierarchy, wrap the reference in a struct that has opEquals, or change the template (you can only use it in source form, so you must have source)? I guess the right way to write templates is "a is b || a==b" anyway, because it handles all cases of equality, regardless of what is defined where.. Anyway, it was just an idea, no need to argue about it - if you don't think it would be useful to you, it probably wouldn't.. xs0
Apr 18 2005
prev sibling next sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
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:

 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.

Apr 14 2005
prev sibling next sibling parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
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
{
}
Apr 14 2005
next sibling parent reply "Kris" <fu bar.com> writes:
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
 {
 }

Apr 14 2005
next sibling parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
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
 {
 }


Apr 14 2005
parent reply kris <fu bar.org> writes:
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
{
}



Apr 14 2005
parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"kris" <fu bar.org> wrote in message 
news:d3nlut$2kl4$1 digitaldaemon.com...
 Just looking for trouble :-)

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

The only solution then would be to eschew the built-in containers. (Which I pretty much do anyway, as it happens. ;/ )
 - 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
{
}




Apr 14 2005
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Kris wrote:
 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);
 }

Why not int opEquals (Comparable o); int opCmp (Comparable o); Moreover: - The presence of a concept of equality certainly doesn't correlate directly with the presence of a natural ordering, so let's not pretend it does. - There's been just as much of a debate over whether Object should have opEquals. My thought is that the default implementation (a given object is equal only to itself) makes sense, and (in theory) makes it possible to use such a class as an AA key. But this doesn't by itself equate to a cause for either keeping or removing Object.opEquals - the 'equal only to itself' behaviour would still be the default if it's removed.
 interface Hashable
 {
   uint toHash();
 }

Would primitive types implement this interface as well? Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Apr 15 2005
next sibling parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message
news:d3o2an$4e$1 digitaldaemon.com...
 Kris wrote:
 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);
 }

Why not int opEquals (Comparable o); int opCmp (Comparable o); Moreover: - The presence of a concept of equality certainly doesn't correlate directly with the presence of a natural ordering, so let's not pretend it does. - There's been just as much of a debate over whether Object should have opEquals. My thought is that the default implementation (a given object is equal only to itself) makes sense, and (in theory) makes it possible to use such a class as an AA key. But this doesn't by itself equate to a cause for either keeping or removing Object.opEquals - the 'equal only to itself' behaviour would still be the default if it's removed.
 interface Hashable
 {
   uint toHash();
 }

Would primitive types implement this interface as well? Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.

Yes, I have also been thinking about that delema. An ordered comparison implies an underlying order. Well, technically speaking, there always is one somewhere in the computer, even if it is meaningless to the intended representation of data, but it should be possible flag a specific kind of item as ordered or unordered, and have that property be inhereted by default. Technically, there should also be a way to indicate "unequal" through the opCmp operator, but that would probably require the results of opCmp to be an enumeration of something like "less", "equal", "greater", "unordered" so that's probably why the opEquals function has independant functionality by default. TZ TZ
Apr 15 2005
parent reply "Walter" <newshound digitalmars.com> writes:
"TechnoZeus" <TechnoZeus PeoplePC.com> wrote in message
news:d3oakv$8qc$1 digitaldaemon.com...
 Technically, there should also be a way to indicate "unequal" through the

an enumeration of something like "less", "equal", "greater", "unordered" so that's probably why the opEquals function has independant functionality by default. You're right. At the moment, it is not practical to create a class that wraps a float because the comparisons won't be able to handle unordered values. I've been thinking about adding an "opCmpX" or something like that that returns 4 states. If it wasn't defined for a class, it would fall back to opCmp. The reason opEquals is a separate implementation is because some types can be equal or not equal, but have no concept of ordering.
Apr 15 2005
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Walter wrote:
<snip>
 You're right. At the moment, it is not practical to create a class that
 wraps a float because the comparisons won't be able to handle unordered
 values.

Moreover, unordered values can't be used in binary search trees and the like (one thing Java uses orderings for). But maybe it's possible to support partially ordered types in such a way that they'll be distinguishable from totally ordered types. And maybe even implement a topological sort on partial orderings. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Apr 18 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Technically, I can't think of any possible type that would be "unorderable"
although it is sometimes good to distinguish between an ordering that is
implicit in the nature of the intended representation, and an ordering that is
derived from the internal representation used to store the data rather than the
nature of what that data was meant to represent.

In other words, the concepts of ">" and "<" could be used to predictably sort
items for the sake of being able to have them at least temporarily in a
predictable order even if that order is unrelated to the nature of the items
being sorted.  For example, if an enum type assigns an integer value internally
to each of it's "unordered" values, then an ordered comparison will have
predictable results at least within a limited context and scope.  For example,
true>false may not give the same results for different implementations, but
would give the same results each time it occurrs within a given implementation
as long as the internal values of "true" and "fales" are not altered.

My point is, there are many grey areas in the concept of ordered or unordered,
and some of them may be useful to have access to by allowing the underlying
"bit patterns" to be accessed, set, compared, etc., independant of the nature
of the data that those bit patterns are intended to represent.  One good
example of this is the idea of using the bit patterns of reference types in
default comparison and assignment operations.

TZ


"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message
news:d400kv$m57$1 digitaldaemon.com...
 Walter wrote:
 <snip>
 You're right. At the moment, it is not practical to create a class that
 wraps a float because the comparisons won't be able to handle unordered
 values.

Moreover, unordered values can't be used in binary search trees and the like (one thing Java uses orderings for). But maybe it's possible to support partially ordered types in such a way that they'll be distinguishable from totally ordered types. And maybe even implement a topological sort on partial orderings. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.

Apr 20 2005
prev sibling parent reply "Kris" <fu bar.com> writes:
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in
 Kris wrote:
 Aye.

 Supposing the "Three Stooges" were removed ... do you have a suggestion


 terms of implementation? Are you thinking in terms of Interfaces? For
 example:

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

Why not int opEquals (Comparable o); int opCmp (Comparable o);

The rest of the class was asleep :-)
 Moreover:

 - The presence of a concept of equality certainly doesn't correlate
 directly with the presence of a natural ordering, so let's not pretend
 it does.

Very true. But if one of them exists for any given class, that object is now exhibiting comparison-traits of the 'deep' variety. If this is done for one, then does it not follow it should be done for the other? In other words, is the Comparable really an indirect indicator of 'deep' comparison? And, does this lead to a suggestion for one method rather than two of them? Is it really /so/ beneficial to have two seperate methods for comparison purposes? I'm just trying to provoke some thought here; not make assertions.
 - There's been just as much of a debate over whether Object should have
 opEquals.  My thought is that the default implementation (a given object
 is equal only to itself) makes sense, and (in theory) makes it possible
 to use such a class as an AA key.  But this doesn't by itself equate to
 a cause for either keeping or removing Object.opEquals - the 'equal only
 to itself' behaviour would still be the default if it's removed.

You must have missed the thread on 'is' vs '==' :-) Defaulting opEqual() to identity conflicts with its role, and opens the door to both misinterpretation and buggy code. Naturally, there's potential for compromise all over the place. But if opEqual() remains in Object, then it should likely have an assert(0), since the developer should actually be using 'is' instead of '=='. But this is bogus too, since the error should be thrown at compile-time rather than runtime. Thus, opEqual() really should come out the root object, such that appropriate compile-time errors are thrown.
 interface Hashable
 {
   uint toHash();
 }

Would primitive types implement this interface as well?

This is part and parcel of the problem with mixing primitives and aggregates into a soup. I won't pretend to have an answer for it, but retaining toHash() within the root object causes technical issues for a compacting GC, and exhibits similar "shallow vs deep" traits as both opCmp() & opEqual(). That is, if an object has something internal considered worthy of use for comparison purposes, then it is rather likely to also have something worthy of hashing (quite possibly the same attribute(s)). Yes? One can understand why Object has these methods right now ~ it represents the easy way out. It's a shame that it's not also the robust way. I'm no OO bigot, but we're talking about the root object here ~ which, at some level, affects every single class written in D. Applying the "good enough" yardstick to this arena is asking for trouble, IMO. And not just from this NG :-) This needs some solid engineering; and I'm glad you keep raising the issue, Stewart.
 Stewart.

 -- 
 My e-mail is valid but not my primary mailbox.  Please keep replies on
 the 'group where everyone may benefit.

Apr 15 2005
parent reply Sean Kelly <sean f4.ca> writes:
In article <d3p3gt$12bt$1 digitaldaemon.com>, Kris says...
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in

 Moreover:

 - The presence of a concept of equality certainly doesn't correlate
 directly with the presence of a natural ordering, so let's not pretend
 it does.

Very true. But if one of them exists for any given class, that object is now exhibiting comparison-traits of the 'deep' variety. If this is done for one, then does it not follow it should be done for the other? In other words, is the Comparable really an indirect indicator of 'deep' comparison? And, does this lead to a suggestion for one method rather than two of them? Is it really /so/ beneficial to have two seperate methods for comparison purposes?

Good question. In my experience, I've never created a class that has one method and not the other, but I wouldn't say that's indicative of a rule. Here's a bad example... say I have a collection of objects that represet classifications. I might want to know if two objects represent the same classification, but ordering a set of such objects might not make a lot of sense. Always preferring compile-time to run-time error checking, it would be nice if I could ensure that my codebase wasn't mistakenly trying to order such objects without running a zillion unit tests.
Defaulting opEqual() to identity conflicts with its role, and opens the door
to both misinterpretation and buggy code. Naturally, there's potential for
compromise all over the place. But if opEqual() remains in Object, then it
should likely have an assert(0), since the developer should actually be
using 'is' instead of '=='. But this is bogus too, since the error should be
thrown at compile-time rather than runtime. Thus, opEqual() really should
come out the root object, such that appropriate compile-time errors are
thrown.

It's too bad that template member functions can't be virtual or you could define these methods in Object and put a static assert in them. What about making Object an abstract base class and declaring these functions but not defining them? Sean
Apr 15 2005
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Sean Kelly wrote:
 In article <d3p3gt$12bt$1 digitaldaemon.com>, Kris says...

Very true. But if one of them exists for any given class, that object is now
exhibiting comparison-traits of the 'deep' variety. If this is done for one,
then does it not follow it should be done for the other? In other words, is
the Comparable really an indirect indicator of 'deep' comparison? And, does
this lead to a suggestion for one method rather than two of them? Is it
really /so/ beneficial to have two seperate methods for comparison purposes?


Yes, so that: - equality comparisons can be made more efficient than ordered comparisons - unequal objects can rank equally in order (such as database records with matching sort keys). <snip>
Defaulting opEqual() to identity conflicts with its role, and opens the door
to both misinterpretation and buggy code. Naturally, there's potential for
compromise all over the place. But if opEqual() remains in Object, then it
should likely have an assert(0), since the developer should actually be
using 'is' instead of '=='. But this is bogus too, since the error should be
thrown at compile-time rather than runtime. Thus, opEqual() really should
come out the root object, such that appropriate compile-time errors are
thrown.


opEqual? What happened to the 's'? As I've said a few times, my understanding is that if someone didn't define opEquals, he/she/it really meant that object references of this class are equal only by being one and the same. So what should happen to AAs when no opEquals is defined? Should they default to ===/is instead of == ? Or should they, artificially and not very logically, be implicitly prevented from use as AA keys? My vote would go to the former, and this is the behaviour provided by the current default opEquals. Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Apr 18 2005
prev sibling parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Well, as long as having other methods doesn't reduce performance, I think it's
better to let Object have as many "useful" methods as you can give it that
would make sense for "most" obects, because people can always choose to
redefine them or simply not use them on objects for which they make no sense.

I think though that the default behavior of opEquals should be to call opCmp
and compare the results of that call with 0, but that's just my opinion.

I also think that the opCmp default behavior should be to compare for identity
first, and if the items being compared are one and the same then return 0 to
indicate "no difference" rather than waste time comparing the contents of an
item to itself... but to compare the contents of the items if they are not one
and the same.

TechnoZeus

"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
 {
 }

Apr 15 2005
prev sibling next sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"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.

I'm not sure how many people know this but you can compare dynamic arrays. For arrays of objects it winds up calling Object.opCmp. So removing Object.opCmp would make array comparison more complex since presumably the compiler would have to check if it was legal or not. Not that I'm arguing opCmp should stay - just that any argument to remove it needs to look at all the places it is used, propose alternatives and objectively assess the pros and cons. int main() { int[] x,y; x = new int[5]; y = new int[7]; printf("shorter %d %d %d\n",x<y, x == y, x is y); y = new int[5]; printf("equal %d %d %d\n",x<y, x == y, x is y); x[3] = 10; printf("greater %d %d %d\n",x<y, x == y, x is y); return 0; } prints shorter 1 0 0 equal 0 1 0 greater 0 0 0 Substitute a class for 'int' above and it continues to work.
Apr 15 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
Actually, the natural extension of your pointing out that you are not sure how
many people are aware of that is exactly why I think it's important to have
such things work "across the board" whenever possible.  It makes the unknown
into something versitile and predictable.  In other words, we can know that
something is (or at least should be) possible, without ever having tried it...
or even having heard of it.

TechnoZeus

"Ben Hinkle" <bhinkle mathworks.com> wrote in message
news:d3p354$1252$1 digitaldaemon.com...
 "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.

I'm not sure how many people know this but you can compare dynamic arrays. For arrays of objects it winds up calling Object.opCmp. So removing Object.opCmp would make array comparison more complex since presumably the compiler would have to check if it was legal or not. Not that I'm arguing opCmp should stay - just that any argument to remove it needs to look at all the places it is used, propose alternatives and objectively assess the pros and cons. int main() { int[] x,y; x = new int[5]; y = new int[7]; printf("shorter %d %d %d\n",x<y, x == y, x is y); y = new int[5]; printf("equal %d %d %d\n",x<y, x == y, x is y); x[3] = 10; printf("greater %d %d %d\n",x<y, x == y, x is y); return 0; } prints shorter 1 0 0 equal 0 1 0 greater 0 0 0 Substitute a class for 'int' above and it continues to work.

Apr 20 2005
prev sibling parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
 2. Leave the current DMD behaviour in, and document it properly.

I would add 2a: leave it in, document it and add a warning to dmd and dlint for classes that define an opCmp that shadows Object.opCmp. In fact a general warnings about shadowing member functions in base classes should say "Foo.opCmp(Foo) shadows Object.opCmp(Object)". For the common case of Object.opCmp it should give a nicer warning that should say something like "Foo.opCmp(Foo) shadows Object.opCmp(Object). Consider defining Foo.opCmp(Object) for associative arrays, sorting and other uses".
Apr 15 2005
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Ben Hinkle" <bhinkle mathworks.com> wrote in message 
news:d3p9qh$17hr$1 digitaldaemon.com...
 2. Leave the current DMD behaviour in, and document it properly.

I would add 2a: leave it in, document it and add a warning to dmd and dlint for classes that define an opCmp that shadows Object.opCmp. In fact a general warnings about shadowing member functions in base classes should say "Foo.opCmp(Foo) shadows Object.opCmp(Object)". For the common case of Object.opCmp it should give a nicer warning that should say something like "Foo.opCmp(Foo) shadows Object.opCmp(Object). Consider defining Foo.opCmp(Object) for associative arrays, sorting and other uses".

But what's the attraction with addressing the symptoms of a disease, when we can prevent the disease? I'm not being sarcastic, I really want to know why people prefer this approach? Does it have _any_ advantages?
Apr 15 2005
next sibling parent reply pragma <pragma_member pathlink.com> writes:
In article <d3pcr2$19r3$1 digitaldaemon.com>, Matthew says...
"Ben Hinkle" <bhinkle mathworks.com> wrote in message 
news:d3p9qh$17hr$1 digitaldaemon.com...
 2. Leave the current DMD behaviour in, and document it properly.

I would add 2a: leave it in, document it and add a warning to dmd and dlint for classes that define an opCmp that shadows Object.opCmp. In fact a general warnings about shadowing member functions in base classes should say "Foo.opCmp(Foo) shadows Object.opCmp(Object)". For the common case of Object.opCmp it should give a nicer warning that should say something like "Foo.opCmp(Foo) shadows Object.opCmp(Object). Consider defining Foo.opCmp(Object) for associative arrays, sorting and other uses".

But what's the attraction with addressing the symptoms of a disease, when we can prevent the disease? I'm not being sarcastic, I really want to know why people prefer this approach? Does it have _any_ advantages?

It requires zero compiler changes. - EricAnderton at yahoo
Apr 15 2005
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"pragma" <pragma_member pathlink.com> wrote in message 
news:d3pfrv$1c70$1 digitaldaemon.com...
 In article <d3pcr2$19r3$1 digitaldaemon.com>, Matthew says...
"Ben Hinkle" <bhinkle mathworks.com> wrote in message
news:d3p9qh$17hr$1 digitaldaemon.com...
 2. Leave the current DMD behaviour in, and document it 
 properly.

I would add 2a: leave it in, document it and add a warning to dmd and dlint for classes that define an opCmp that shadows Object.opCmp. In fact a general warnings about shadowing member functions in base classes should say "Foo.opCmp(Foo) shadows Object.opCmp(Object)". For the common case of Object.opCmp it should give a nicer warning that should say something like "Foo.opCmp(Foo) shadows Object.opCmp(Object). Consider defining Foo.opCmp(Object) for associative arrays, sorting and other uses".

But what's the attraction with addressing the symptoms of a disease, when we can prevent the disease? I'm not being sarcastic, I really want to know why people prefer this approach? Does it have _any_ advantages?

It requires zero compiler changes.

Sure. But is that a good reason, in a pre-1.0 language that aims to avoid making the mistakes of its predecessors? What's wrong with change at this stage?
Apr 15 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
What you are calling a disease, in this case, I think of as a useful and
powerful feature.  Perhaps that's why people would rather treat it than cure
it.  Why fix it if it's not broken?

TZ

"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message
news:d3pn7e$1hth$1 digitaldaemon.com...
 "pragma" <pragma_member pathlink.com> wrote in message
 news:d3pfrv$1c70$1 digitaldaemon.com...
 In article <d3pcr2$19r3$1 digitaldaemon.com>, Matthew says...
"Ben Hinkle" <bhinkle mathworks.com> wrote in message
news:d3p9qh$17hr$1 digitaldaemon.com...
 2. Leave the current DMD behaviour in, and document it
 properly.

I would add 2a: leave it in, document it and add a warning to dmd and dlint for classes that define an opCmp that shadows Object.opCmp. In fact a general warnings about shadowing member functions in base classes should say "Foo.opCmp(Foo) shadows Object.opCmp(Object)". For the common case of Object.opCmp it should give a nicer warning that should say something like "Foo.opCmp(Foo) shadows Object.opCmp(Object). Consider defining Foo.opCmp(Object) for associative arrays, sorting and other uses".

But what's the attraction with addressing the symptoms of a disease, when we can prevent the disease? I'm not being sarcastic, I really want to know why people prefer this approach? Does it have _any_ advantages?

It requires zero compiler changes.

Sure. But is that a good reason, in a pre-1.0 language that aims to avoid making the mistakes of its predecessors? What's wrong with change at this stage?

Apr 20 2005
prev sibling next sibling parent reply xs0 <xs0 xs0.com> writes:
Matthew wrote:
 "Ben Hinkle" <bhinkle mathworks.com> wrote in message 
 news:d3p9qh$17hr$1 digitaldaemon.com...
 
2. Leave the current DMD behaviour in, and document it properly.

I would add 2a: leave it in, document it and add a warning to dmd and dlint for classes that define an opCmp that shadows Object.opCmp. In fact a general warnings about shadowing member functions in base classes should say "Foo.opCmp(Foo) shadows Object.opCmp(Object)". For the common case of Object.opCmp it should give a nicer warning that should say something like "Foo.opCmp(Foo) shadows Object.opCmp(Object). Consider defining Foo.opCmp(Object) for associative arrays, sorting and other uses".

But what's the attraction with addressing the symptoms of a disease, when we can prevent the disease? I'm not being sarcastic, I really want to know why people prefer this approach? Does it have _any_ advantages?

You can sort an Object[] without caring what the actual types are? (of course, as long as all classes involved implement opCmp(Object)) xs0
Apr 15 2005
next sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <d3pg6t$1c8i$1 digitaldaemon.com>, xs0 says...
 
 I'm not being sarcastic, I really want to know why people prefer 
 this approach? Does it have _any_ advantages? 

You can sort an Object[] without caring what the actual types are? (of course, as long as all classes involved implement opCmp(Object))

But is this an advantage? I've personally never found a reason to compare to entirely unrelated types. Type safety is a Good Thing. Sean
Apr 15 2005
parent "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"Sean Kelly" <sean f4.ca> wrote in message
news:d3phhq$1dlj$1 digitaldaemon.com...
 In article <d3pg6t$1c8i$1 digitaldaemon.com>, xs0 says...
 I'm not being sarcastic, I really want to know why people prefer
 this approach? Does it have _any_ advantages?

You can sort an Object[] without caring what the actual types are? (of course, as long as all classes involved implement opCmp(Object))

But is this an advantage? I've personally never found a reason to compare to entirely unrelated types. Type safety is a Good Thing. Sean

Yes, there are huge advantages to it in specific cases where that is what the software designer wants to do. Never assume that your not having found something precludes it's existance. That's the beauty of generic functionality. In addition to being applicable to a wide range of known situations, it's applicable to things nobody's even thought of yet. Besides, removing it would only increase the work that the compiler would have to perform in some cases and increase the work that the programmer would have to perform in other cases. There are no cases where removing such an ability would reduce the amount of coding necessary to produce an algorithm that would perform a specific task, and removing such an ability would commonly have a negative impact on performance while rarely if ever having a positive impact. TZ
Apr 20 2005
prev sibling parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"xs0" <xs0 xs0.com> wrote in message 
news:d3pg6t$1c8i$1 digitaldaemon.com...
 Matthew wrote:
 "Ben Hinkle" <bhinkle mathworks.com> wrote in message 
 news:d3p9qh$17hr$1 digitaldaemon.com...

2. Leave the current DMD behaviour in, and document it properly.

I would add 2a: leave it in, document it and add a warning to dmd and dlint for classes that define an opCmp that shadows Object.opCmp. In fact a general warnings about shadowing member functions in base classes should say "Foo.opCmp(Foo) shadows Object.opCmp(Object)". For the common case of Object.opCmp it should give a nicer warning that should say something like "Foo.opCmp(Foo) shadows Object.opCmp(Object). Consider defining Foo.opCmp(Object) for associative arrays, sorting and other uses".

But what's the attraction with addressing the symptoms of a disease, when we can prevent the disease? I'm not being sarcastic, I really want to know why people prefer this approach? Does it have _any_ advantages?

You can sort an Object[] without caring what the actual types are? (of course, as long as all classes involved implement opCmp(Object))

But sorting heterogeneous types is only meaningful in a subset of cases, and all those cases are accounted for in the alternative proposal. I meant what advantages does the current approach have over the proposed approach? Since it has non-trivial disadvantages, there has to be advantages. Otherwise the language can be said to be just a mix of arbitrary illogical decisions, surely?
Apr 15 2005
parent reply xs0 <xs0 xs0.com> writes:
Matthew wrote:
 "xs0" <xs0 xs0.com> wrote in message 
 news:d3pg6t$1c8i$1 digitaldaemon.com...
 
Matthew wrote:

"Ben Hinkle" <bhinkle mathworks.com> wrote in message 
news:d3p9qh$17hr$1 digitaldaemon.com...


2. Leave the current DMD behaviour in, and document it properly.

I would add 2a: leave it in, document it and add a warning to dmd and dlint for classes that define an opCmp that shadows Object.opCmp. In fact a general warnings about shadowing member functions in base classes should say "Foo.opCmp(Foo) shadows Object.opCmp(Object)". For the common case of Object.opCmp it should give a nicer warning that should say something like "Foo.opCmp(Foo) shadows Object.opCmp(Object). Consider defining Foo.opCmp(Object) for associative arrays, sorting and other uses".

But what's the attraction with addressing the symptoms of a disease, when we can prevent the disease? I'm not being sarcastic, I really want to know why people prefer this approach? Does it have _any_ advantages?

You can sort an Object[] without caring what the actual types are? (of course, as long as all classes involved implement opCmp(Object))

But sorting heterogeneous types is only meaningful in a subset of cases, and all those cases are accounted for in the alternative proposal.

Who said anything about heteregeneous types? Object[] means whatever, including Foo[], because you can implicitly cast Foo[] to Object[]. I.e. everything is an Object. How exactly would this work, if Object was without opCmp: void checkRange(Object a, Object b, Object c) { if (a<=b && b<=c) return; logger.logError("Range check failed"); } Now this is not about comparing different types, it's about comparing any types. xs0
Apr 15 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
 Who said anything about heteregeneous types? Object[] means whatever, 
 including Foo[], because you can implicitly cast Foo[] to Object[]. I.e. 
 everything is an Object.

hmm. It is pretty scary if we are allowed to do class Foo{int foo;} void main() { Foo[] x; x.length = 2; Object[] y = x; // implicitly cast y[0] = new Object; x[0].foo = 10; // Object is not a Foo - yikes! }
Apr 15 2005
next sibling parent reply xs0 <xs0 xs0.com> writes:
Ben Hinkle wrote:
Who said anything about heteregeneous types? Object[] means whatever, 
including Foo[], because you can implicitly cast Foo[] to Object[]. I.e. 
everything is an Object.

hmm. It is pretty scary if we are allowed to do class Foo{int foo;} void main() { Foo[] x; x.length = 2; Object[] y = x; // implicitly cast y[0] = new Object; x[0].foo = 10; // Object is not a Foo - yikes! }

Well, what does this have to do with opCmp? :) And you can't do that anyway, Object doesn't have a .foo property, so you'll get a compile error.. xs0
Apr 15 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"xs0" <xs0 xs0.com> wrote in message news:d3q40g$1qbt$2 digitaldaemon.com...
 Ben Hinkle wrote:
Who said anything about heteregeneous types? Object[] means whatever, 
including Foo[], because you can implicitly cast Foo[] to Object[]. I.e. 
everything is an Object.

hmm. It is pretty scary if we are allowed to do class Foo{int foo;} void main() { Foo[] x; x.length = 2; Object[] y = x; // implicitly cast y[0] = new Object; x[0].foo = 10; // Object is not a Foo - yikes! }

Well, what does this have to do with opCmp? :)

I saw the statement that Foo[] is implicitly castable to Object[] and I said to myself "no way" and then I went to get the compiler error and was surprised that it didn't error.
 And you can't do that anyway, Object doesn't have a .foo property, so 
 you'll get a compile error..

Notice "x" is declared as Foo[] so x[0].foo is legal. Scarily enough the example compiled and ran. It should have errored at the implicit cast. I'll probably put something on D.bugs soon...
Apr 15 2005
parent xs0 <xs0 xs0.com> writes:
Ben Hinkle wrote:
 "xs0" <xs0 xs0.com> wrote in message news:d3q40g$1qbt$2 digitaldaemon.com...
 
Ben Hinkle wrote:

Who said anything about heteregeneous types? Object[] means whatever, 
including Foo[], because you can implicitly cast Foo[] to Object[]. I.e. 
everything is an Object.

hmm. It is pretty scary if we are allowed to do class Foo{int foo;} void main() { Foo[] x; x.length = 2; Object[] y = x; // implicitly cast y[0] = new Object; x[0].foo = 10; // Object is not a Foo - yikes! }

Well, what does this have to do with opCmp? :)

I saw the statement that Foo[] is implicitly castable to Object[] and I said to myself "no way" and then I went to get the compiler error and was surprised that it didn't error.

Yes way: A dynamic array T[] can be implicitly converted to one of the following: * T* * U[] where U is a base class of T. * U* where U is a base class of T. * void*
And you can't do that anyway, Object doesn't have a .foo property, so 
you'll get a compile error..

Notice "x" is declared as Foo[] so x[0].foo is legal. Scarily enough the example compiled and ran. It should have errored at the implicit cast. I'll probably put something on D.bugs soon...

Sorry, I misread x[0] as y[0]. But how is it a bug (in the language)? Foo[] is Object[] in the sense that every Foo is an Object. Later, when you insert an Object, it's not Foo[] anymore, but you then use an "implicit explicit cast" back to Foo[], which is the error in this case. xs0
Apr 15 2005
prev sibling parent reply "TechnoZeus" <TechnoZeus PeoplePC.com> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote in message
news:d3q2tm$1pag$1 digitaldaemon.com...
 Who said anything about heteregeneous types? Object[] means whatever,
 including Foo[], because you can implicitly cast Foo[] to Object[]. I.e.
 everything is an Object.

hmm. It is pretty scary if we are allowed to do class Foo{int foo;} void main() { Foo[] x; x.length = 2; Object[] y = x; // implicitly cast y[0] = new Object; x[0].foo = 10; // Object is not a Foo - yikes! }

Don't be scared so easily. :) Seriously though, the only problem with that is the potential that the programmer may not have meant to do an identity assignment when they typed "y=x" and therefore may not have planned for the side effects of x and y having the same identity. A situation that could be easily avoided if separate value and identity assignment operators were introduces. I don't see anything being done there that lacks the "potential to be useful" in the right situation. Sure, it could be misused, but that's true of anything that can be used at all. The only hazard I see is the potential for it to be done accidentally, and that's not likely. TZ
Apr 20 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"TechnoZeus" <TechnoZeus PeoplePC.com> wrote in message 
news:d457b2$2oai$1 digitaldaemon.com...
 "Ben Hinkle" <ben.hinkle gmail.com> wrote in message 
 news:d3q2tm$1pag$1 digitaldaemon.com...
 Who said anything about heteregeneous types? Object[] means whatever,
 including Foo[], because you can implicitly cast Foo[] to Object[]. 
 I.e.
 everything is an Object.

hmm. It is pretty scary if we are allowed to do class Foo{int foo;} void main() { Foo[] x; x.length = 2; Object[] y = x; // implicitly cast y[0] = new Object; x[0].foo = 10; // Object is not a Foo - yikes! }

Don't be scared so easily. :) Seriously though, the only problem with that is the potential that the programmer may not have meant to do an identity assignment when they typed "y=x" and therefore may not have planned for the side effects of x and y having the same identity. A situation that could be easily avoided if separate value and identity assignment operators were introduces. I don't see anything being done there that lacks the "potential to be useful" in the right situation. Sure, it could be misused, but that's true of anything that can be used at all. The only hazard I see is the potential for it to be done accidentally, and that's not likely.

Here's another example that might be more common: class Foo{} class Bar:Foo{} void clamp(Foo[] x) { // cheesy function that changes x foreach(inout Foo y; x) { if (y < 0) y = new Foo(0); } } ... Bar[] y; ... fill(y); // y potentially has a Foo in it - a type violation. Implicitly casting shouldn't open up such a large hole in the type system. At least in C violating the type system requires a cast.
Apr 20 2005
parent reply xs0 <xs0 xs0.com> writes:
 Here's another example that might be more common:
 class Foo{}
 class Bar:Foo{}
 void clamp(Foo[] x) { // cheesy function that changes x
   foreach(inout Foo y; x) {
     if (y < 0)  y = new Foo(0);
   }
 }
 ....
 Bar[] y;
 ....
 fill(y); // y potentially has a Foo in it - a type violation.

But here, you're calling basically fillSomeElementsWithFoos(Bar[]). You obviously can't expect the result to be Bars only.. I mean, the problem is not the implicit cast, but the type of y, when used with fill(). Even if you call fill(cast(Foo[])y), it can still contain a Foo, while its type is Bar[].. My point is that you need to know what your functions do, otherwise you'll run into problems, with implicit casting of arrays or not. If implicit casting of arrays were to be removed, it would mean that each function that works on an array works exactly on that kind of array and nothing else. The result would be just requiring a ton of casts, which solves nothing, yet could cause more problems than it solves - in the case above, you would type "fill(cast(Foo[])y)". But then, when you write fill(Bar[]) to handle Bar[] filling, it won't get called, because you cast the real type away.. xs0
Apr 20 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"xs0" <xs0 xs0.com> wrote in message news:d45psv$l74$1 digitaldaemon.com...
 Here's another example that might be more common:
 class Foo{}
 class Bar:Foo{}
 void clamp(Foo[] x) { // cheesy function that changes x
   foreach(inout Foo y; x) {
     if (y < 0)  y = new Foo(0);
   }
 }
 ....
 Bar[] y;
 ....
 fill(y); // y potentially has a Foo in it - a type violation.

But here, you're calling basically fillSomeElementsWithFoos(Bar[]). You obviously can't expect the result to be Bars only.. I mean, the problem is not the implicit cast, but the type of y, when used with fill(). Even if you call fill(cast(Foo[])y), it can still contain a Foo, while its type is Bar[]..

A core principle of upcasting is substitutability. If Bar is derived from Foo then everything that takes a Foo can take a Bar. With arrays, though, an array of Foo cannot be substituted with an array of Bar since an array of Foo can hold an aribitrary Foo while an array of Bar cannot. Implicitly upcasting containers is a big type safety hole if the result is allowed to change the contents of the container.
 My point is that you need to know what your functions do, otherwise you'll 
 run into problems, with implicit casting of arrays or not.

Sure, but with enough care we wouldn't have any bugs at all and we'd have no need for type checking or type-safety. Imagine how hard it would be to track down something as subtle as this.
 If implicit casting of arrays were to be removed, it would mean that each 
 function that works on an array works exactly on that kind of array and 
 nothing else.

True, but that's life. I believe sacrificing type-safety is too high a price to pay for the convenience of implicit array coversions. In my D coding, for instance, I haven't ever needed implicit array conversions.
 The result would be just requiring a ton of casts, which solves nothing, 
 yet could cause more problems than it solves - in the case above, you 
 would type "fill(cast(Foo[])y)". But then, when you write fill(Bar[]) to 
 handle Bar[] filling, it won't get called, because you cast the real type 
 away..

Casting is the accepted way to blow away type safety. Let's keep it that way.
Apr 20 2005
parent reply xs0 <xs0 xs0.com> writes:
Ben Hinkle wrote:
 Implicitly 
 upcasting containers is a big type safety hole if the result is allowed to 
 change the contents of the container.

 Casting is the accepted way to blow away type safety. Let's keep it that 
 way. 

See, it's not that simple. To have more type safety, you'd require more casts, but they result in less type safety, so it may actually be conterproductive.. Java and C++ both allow implicit array upcasts, too, so I wouldn't say that people can't live with it? OTOH, If you look at Java's generics spec, they addressed this issue somewhat by having parameters be one of (with List as an example) List<T> - accepts exactly T List<? super T> - accepts T and T's supertypes List<? extends T> - accepts T and T's subtypes The first is read/write, the second is write-only, the third is read-only, for obvious reasons. Considering how write-only is significantly rarer than the other two, perhaps the best option with D would be to get support and a new syntax for demanding an exact type in function parameters, which is where most of the problem is. Perhaps void func(Type! a) void func(Type![] a) void func(Type!(int)! a) void func(Type!(int)![] a) Read-only functions would work as they do now, which is fine because they don't suffer from type unsafety. Read/write functions would be able to demand an exact type (which may or may not be useful outside the context of arrays, but I don't see why it shouldn't be allowed). Finally, for write-only functions, I guess the way to go would be again requiring an exact type, which'd require an explicit cast. However, this case of casting is not as problematic, because if you have like a FooSuperclass[] and cast it to Foo[] when calling a func, you're still keeping it locally as a FooSuperclass[], which it still is even after it gets filled with Foos (unlike casting a Subclass[] to Foo[], which is then no longer a Subclass[]). Finally, to solve the local issue of Foo[] a=...; Object[] b=a; b[0]=new Object; a[0].do(); I'd say that implicit casting of arrays can only be done when calling functions, where it's only really needed anyway. Locally, you can always use the other type in the first place, I guess.. Thoughts? xs0
Apr 20 2005
parent reply "Ben Hinkle" <bhinkle mathworks.com> writes:
"xs0" <xs0 xs0.com> wrote in message news:d4632l$uke$1 digitaldaemon.com...
 Ben Hinkle wrote:
 Implicitly upcasting containers is a big type safety hole if the result 
 is allowed to change the contents of the container.

 Casting is the accepted way to blow away type safety. Let's keep it that 
 way.

See, it's not that simple. To have more type safety, you'd require more casts, but they result in less type safety, so it may actually be conterproductive..

I'm suggesting the user be more explicit about when they are risking type safety. The implicit cast is hiding some potentially very dangerous code.
 Java and C++ both allow implicit array upcasts, too, so I wouldn't say 
 that people can't live with it?

Note Java allows the implicit cast but doesn't allow the assignment that would break the type-safety. http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html#11430 I'm not suggesting D go the Java route and store all the run-time array type information. I do suggest D make the coder more explicitly acknowledge when they are taking a risk with type safety. I agree C++ allows implicit pointer upcasting but everyone grumbles about C++ type-safety holes like that. It's one of C++'s weaknesses in following C so closely.
Apr 20 2005
parent reply xs0 <xs0 xs0.com> writes:
Ben Hinkle wrote:
Implicitly upcasting containers is a big type safety hole if the result 
is allowed to change the contents of the container.

Casting is the accepted way to blow away type safety. Let's keep it that 
way.

See, it's not that simple. To have more type safety, you'd require more casts, but they result in less type safety, so it may actually be conterproductive..

I'm suggesting the user be more explicit about when they are risking type safety. The implicit cast is hiding some potentially very dangerous code.

I agree, but I don't think forcing them to explicitly cast is the best solution. See my previous post for what I'd suggest. Another option is simply using inout, although in that case you can't cast even if you want to (at least not very easily - you need a new var and a cast back).. btw, what I suggested is exactly the same regarding type safety as inout, the only inout's downside is that the caller's reference can be overwritten..
Java and C++ both allow implicit array upcasts, too, so I wouldn't say 
that people can't live with it?

Note Java allows the implicit cast but doesn't allow the assignment that would break the type-safety.

True, yet it still only happens at run-time, and it may even be unneeded: Object[] blah=someFunc(); // returns a new String[]; blah[0]=new Whatever(blah[0]); Although it's true - in D such an error will most probably not even get detected right away, which can probably cause quite a havoc, if you're lucky.. Again, I don't think forcing explicit casts will help; if a change is going to happen, it should be where the function is, not where the caller is (in other words, type safety should be enforced already when defining functions, not when calling them).
 I'm not suggesting D go the Java route and store all the run-time array type 
 information. I do suggest D make the coder more explicitly acknowledge when 
 they are taking a risk with type safety. 

 everyone grumbles about C++ type-safety holes. It's
 one of C++'s weaknesses in following C so closely. 

Agreed on both counts. xs0
Apr 20 2005
parent reply Georg Wrede <georg.wrede nospam.org> writes:
xs0 wrote:
 Ben Hinkle wrote:
 
 Implicitly upcasting containers is a big type safety hole if
 the result is allowed to change the contents of the container.

 Casting is the accepted way to blow away type safety. Let's
 keep it that way.

See, it's not that simple. To have more type safety, you'd require more casts, but they result in less type safety, so it may actually be conterproductive..

I'm suggesting the user be more explicit about when they are risking type safety. The implicit cast is hiding some potentially very dangerous code.

I agree, but I don't think forcing them to explicitly cast is the best solution. See my previous post for what I'd suggest. Another option is simply using inout, although in that case you can't cast even if you want to (at least not very easily - you need a new var and a cast back).. btw, what I suggested is exactly the same regarding type safety as inout, the only inout's downside is that the caller's reference can be overwritten..
 Java and C++ both allow implicit array upcasts, too, so I
 wouldn't say that people can't live with it?

Note Java allows the implicit cast but doesn't allow the assignment that would break the type-safety.

True, yet it still only happens at run-time, and it may even be unneeded: Object[] blah=someFunc(); // returns a new String[]; blah[0]=new Whatever(blah[0]);

Anybody writing that piece of code is asking for First Blood. Out of his own nose. There are limits to things. We don't want D to be jerk-proof. Probably there ought to be a law that says this kind of people should not have cutlery in the kitchen. (Why? Well, they might carve the dog or the postman, just out of ignorance: Oh, I just wanted to check if this knife is as sharp as they say on TV, Officer.)
 Although it's true - in D such an error will most probably not even
 get detected right away, which can probably cause quite a havoc, if
 you're lucky.. Again, I don't think forcing explicit casts will help;

Apr 20 2005
parent reply xs0 <xs0 xs0.com> writes:
 True, yet it still only happens at run-time, and it may even be
 unneeded:

 Object[] blah=someFunc(); // returns a new String[];
 blah[0]=new Whatever(blah[0]);

Anybody writing that piece of code is asking for First Blood. Out of his own nose.

Why exactly? The point was that a) the code handles any Object b) Java would needlessly throw an exception here
 There are limits to things. We don't want D to be jerk-proof. Probably 
 there ought to be a law that says this kind of people should not have 
 cutlery in the kitchen. (Why? Well, they might carve the dog or the 
 postman, just out of ignorance: Oh, I just wanted to check if this knife 
 is as sharp as they say on TV, Officer.)

Bah, I can think of some other laws as well :P xs0
Apr 20 2005
parent reply Georg Wrede <georg.wrede nospam.org> writes:
xs0 wrote:
 
 True, yet it still only happens at run-time, and it may even be
 unneeded:

 Object[] blah=someFunc(); // returns a new String[];
 blah[0]=new Whatever(blah[0]);

Anybody writing that piece of code is asking for First Blood. Out of his own nose.

Why exactly? The point was that a) the code handles any Object b) Java would needlessly throw an exception here

If the code handles "any Object", then why be surprised if the compiler doesn't catch the situation where you suddenly don't want it to?
 There are limits to things. We don't want D to be jerk-proof. Probably 
 there ought to be a law that says this kind of people should not have 
 cutlery in the kitchen. (Why? Well, they might carve the dog or the 
 postman, just out of ignorance: Oh, I just wanted to check if this 
 knife is as sharp as they say on TV, Officer.)

Bah, I can think of some other laws as well :P xs0

Apr 20 2005
parent reply xs0 <xs0 xs0.com> writes:
Georg Wrede wrote:
 xs0 wrote:
 
 True, yet it still only happens at run-time, and it may even be
 unneeded:

 Object[] blah=someFunc(); // returns a new String[];
 blah[0]=new Whatever(blah[0]);

Anybody writing that piece of code is asking for First Blood. Out of his own nose.

Why exactly? The point was that a) the code handles any Object b) Java would needlessly throw an exception here

If the code handles "any Object", then why be surprised if the compiler doesn't catch the situation where you suddenly don't want it to?

I don't get what you're trying to say, sorry.. xs0
Apr 21 2005
parent Georg Wrede <georg.wrede nospam.org> writes:
xs0 wrote:
 If the code handles "any Object", then why be surprised if the 
 compiler doesn't catch the situation where you suddenly don't want
 it to?

I don't get what you're trying to say, sorry..

Below is what I responded to:
 Object[] blah=someFunc(); // returns a new String[];
 blah[0]=new Whatever(blah[0]);
 
 Although it's true - in D such an error will most probably not even
 get detected right away, which can probably cause quite a havoc, if
 you're lucky.. Again, I don't think forcing explicit casts will help;
 if a change is going to happen, it should be where the function is,
 not where the caller is (in other words, type safety should be
 enforced already when defining functions, not when calling them).

The code and the explanation looked as if having a reference to an instance of "Whatever" in the array was not welcome. The text mentioned "such an error". This gave me the impression that the coder had created an Object[] without intending it to accept precisely anything.
Apr 21 2005
prev sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message 
news:d3pcr2$19r3$1 digitaldaemon.com...
 "Ben Hinkle" <bhinkle mathworks.com> wrote in message 
 news:d3p9qh$17hr$1 digitaldaemon.com...
 2. Leave the current DMD behaviour in, and document it properly.

I would add 2a: leave it in, document it and add a warning to dmd and dlint for classes that define an opCmp that shadows Object.opCmp. In fact a general warnings about shadowing member functions in base classes should say "Foo.opCmp(Foo) shadows Object.opCmp(Object)". For the common case of Object.opCmp it should give a nicer warning that should say something like "Foo.opCmp(Foo) shadows Object.opCmp(Object). Consider defining Foo.opCmp(Object) for associative arrays, sorting and other uses".

But what's the attraction with addressing the symptoms of a disease, when we can prevent the disease? I'm not being sarcastic, I really want to know why people prefer this approach? Does it have _any_ advantages?

I'd like to see a more complete description of what would change before making up my mind. If we just remove Object.opCmp obviously many things won't work (eg, aa's, sorting, dynamic array operations, maybe more) so what exactly won't work and what will have to change to get it to work? Redoing large chunks of the TypeInfo system isn't trivial IMO. Maybe I'm just being thick but I'd like to see more details.
Apr 15 2005
next sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <d3pq4b$1jhe$1 digitaldaemon.com>, Ben Hinkle says...
I'd like to see a more complete description of what would change before 
making up my mind. If we just remove Object.opCmp obviously many things 
won't work (eg, aa's, sorting, dynamic array operations, maybe more) so what 
exactly won't work and what will have to change to get it to work? Redoing 
large chunks of the TypeInfo system isn't trivial IMO. Maybe I'm just being 
thick but I'd like to see more details. 

Moving the methods to interfaces *almost* works, and the changes really aren't too bad on the library side (I gave this a whirl with Ares--there's a branched version on my website if you're interested). But this approach also requires changes to portions of DMD that aren't shipped in source form, so estimating their scope is somewhat difficult. Maybe someone with GDC experience could chime in? Sean
Apr 15 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"Sean Kelly" <sean f4.ca> wrote in message 
news:d3pqsk$1jsl$1 digitaldaemon.com...
 In article <d3pq4b$1jhe$1 digitaldaemon.com>, Ben Hinkle says...
I'd like to see a more complete description of what would change before
making up my mind. If we just remove Object.opCmp obviously many things
won't work (eg, aa's, sorting, dynamic array operations, maybe more) so 
what
exactly won't work and what will have to change to get it to work? Redoing
large chunks of the TypeInfo system isn't trivial IMO. Maybe I'm just 
being
thick but I'd like to see more details.

Moving the methods to interfaces *almost* works, and the changes really aren't too bad on the library side (I gave this a whirl with Ares--there's a branched version on my website if you're interested). But this approach also requires changes to portions of DMD that aren't shipped in source form, so estimating their scope is somewhat difficult. Maybe someone with GDC experience could chime in?

The interface would presumably be Comparable.opCmp(Comparable), correct? I thought the primary complaint against opCmp was that people would define a class Foo with Foo.opCmp(Foo) and expect it to work. With Comparable to get things to work one has to know about Comparable and write Foo.opCmp(Comparable) instead of Foo.opCmp(Object). Is this what the interfaces proposal is? I'm asking because I'm not sure exactly what the details of the proposal are. If that is the proposal then what are the benefits?
Apr 15 2005
next sibling parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote in message 
news:d3prvs$1kms$1 digitaldaemon.com...
 "Sean Kelly" <sean f4.ca> wrote in message 
 news:d3pqsk$1jsl$1 digitaldaemon.com...
 In article <d3pq4b$1jhe$1 digitaldaemon.com>, Ben Hinkle says...
I'd like to see a more complete description of what would change 
before
making up my mind. If we just remove Object.opCmp obviously many 
things
won't work (eg, aa's, sorting, dynamic array operations, maybe 
more) so what
exactly won't work and what will have to change to get it to 
work? Redoing
large chunks of the TypeInfo system isn't trivial IMO. Maybe I'm 
just being
thick but I'd like to see more details.

Moving the methods to interfaces *almost* works, and the changes really aren't too bad on the library side (I gave this a whirl with Ares--there's a branched version on my website if you're interested). But this approach also requires changes to portions of DMD that aren't shipped in source form, so estimating their scope is somewhat difficult. Maybe someone with GDC experience could chime in?

The interface would presumably be Comparable.opCmp(Comparable), correct? I thought the primary complaint against opCmp was that people would define a class Foo with Foo.opCmp(Foo) and expect it to work. With Comparable to get things to work one has to know about Comparable and write Foo.opCmp(Comparable) instead of Foo.opCmp(Object). Is this what the interfaces proposal is? I'm asking because I'm not sure exactly what the details of the proposal are. If that is the proposal then what are the benefits?

I think there are two (or more) proposals here. My idea doesn't involve a particular interface, rather heterogeneity is supported as a natural consequence of the requirement for all types in the array (or whatever) to be related polymorphically. I'm pretty sure what I proposed in March - "A proposal for a new, improved opCmp() [WAS: Round-up of the excuses for keeping Object.opCmp, and rebuttals to them]" (d0lsv5$1496$1 digitaldaemon.com) - still accurately represents my thoughts. Matthew P.S. Anyone advise on how to get a clickable message link from an entry in Outlook Express? I know it's done, because some of you do it. :-)
Apr 15 2005
next sibling parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
 The interface would presumably be Comparable.opCmp(Comparable), correct? 
 I thought the primary complaint against opCmp was that people would 
 define a class Foo with Foo.opCmp(Foo) and expect it to work. With 
 Comparable to get things to work one has to know about Comparable and 
 write Foo.opCmp(Comparable) instead of Foo.opCmp(Object). Is this what 
 the interfaces proposal is? I'm asking because I'm not sure exactly what 
 the details of the proposal are. If that is the proposal then what are 
 the benefits?

I think there are two (or more) proposals here. My idea doesn't involve a particular interface, rather heterogeneity is supported as a natural consequence of the requirement for all types in the array (or whatever) to be related polymorphically.

Yeah - the C++-style of using compile-time generics instead of run-time dispatching (Object or Comparable) seems like the most reasonable alternative to me at the moment - though it would also probably disrupt the TypeInfo system the most. The TypeInfos are a way to get generic type hooks without using templates or overloading. My gut is leaning towards either keeping Object.opCmp dynamic binding or ditching that for compile-time binding. The Comparable solution seems like a fairly small modification of Object.opCmp that doesn't really give enough benefits over Object.opCmp. But that's just my gut feelings without knowing much of anything about the actual proposals and their impact...
 I'm pretty sure what I proposed in March - "A proposal for a new, improved 
 opCmp() [WAS: Round-up of the excuses for keeping Object.opCmp, and 
 rebuttals to them]" (d0lsv5$1496$1 digitaldaemon.com) - still accurately 
 represents my thoughts.

I'll try to hunt that down.
 Matthew

 P.S. Anyone advise on how to get a clickable message link from an entry in 
 Outlook Express? I know it's done, because some of you do it. :-)

That would be nice because I only know how to point to the forum page on the DigitalMars site and that only takes you to a particular message and not the thread.
Apr 15 2005
next sibling parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote in message 
news:d3pvun$1n8i$1 digitaldaemon.com...
 The interface would presumably be Comparable.opCmp(Comparable), 
 correct? I thought the primary complaint against opCmp was that 
 people would define a class Foo with Foo.opCmp(Foo) and expect 
 it to work. With Comparable to get things to work one has to 
 know about Comparable and write Foo.opCmp(Comparable) instead of 
 Foo.opCmp(Object). Is this what the interfaces proposal is? I'm 
 asking because I'm not sure exactly what the details of the 
 proposal are. If that is the proposal then what are the 
 benefits?

I think there are two (or more) proposals here. My idea doesn't involve a particular interface, rather heterogeneity is supported as a natural consequence of the requirement for all types in the array (or whatever) to be related polymorphically.

Yeah - the C++-style of using compile-time generics instead of run-time dispatching (Object or Comparable) seems like the most reasonable alternative to me at the moment - though it would also probably disrupt the TypeInfo system the most. The TypeInfos are a way to get generic type hooks without using templates or overloading. My gut is leaning towards either keeping Object.opCmp dynamic binding or ditching that for compile-time binding. The Comparable solution seems like a fairly small modification of Object.opCmp that doesn't really give enough benefits over Object.opCmp. But that's just my gut feelings without knowing much of anything about the actual proposals and their impact...

Excellent point. I'd suggest that we downgrade any enthusiasm for the interface-based approach (and upgrade it for my proposal of course ... <laughing hysterically; kids looking on bemused "shush daddy!">
Apr 15 2005
prev sibling parent reply J C Calvarese <jcc7 cox.net> writes:
Ben Hinkle wrote:
...

P.S. Anyone advise on how to get a clickable message link from an entry in 
Outlook Express? I know it's done, because some of you do it. :-)

That would be nice because I only know how to point to the forum page on the DigitalMars site and that only takes you to a particular message and not the thread.

If you go to http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D, and click on the "Subject" tab, you can see the message titles. Since they're alphabetized, the first page currently has entries for "" (no subject), "!(null is hkey) ??", and other subjects which begin with punctuation symbols. You'll probably need to click the "More" button a few times to get close to what you're looking for. (Is that what you want or did I answer the wrong question?) -- jcc7 http://jcc_7.tripod.com/d/
Apr 17 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
"J C Calvarese" <jcc7 cox.net> wrote in message 
news:d3ume6$2h3g$1 digitaldaemon.com...
 Ben Hinkle wrote:
 ...

P.S. Anyone advise on how to get a clickable message link from an entry 
in Outlook Express? I know it's done, because some of you do it. :-)

That would be nice because I only know how to point to the forum page on the DigitalMars site and that only takes you to a particular message and not the thread.

If you go to http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D, and click on the "Subject" tab, you can see the message titles. Since they're alphabetized, the first page currently has entries for "" (no subject), "!(null is hkey) ??", and other subjects which begin with punctuation symbols. You'll probably need to click the "More" button a few times to get close to what you're looking for. (Is that what you want or did I answer the wrong question?)

I meant all I know how to do is this: digitalmars.D/6809 How can I get a link to the whole thread instead of just a message in the thread?
Apr 17 2005
parent reply J C Calvarese <jcc7 cox.net> writes:
Ben Hinkle wrote:
 "J C Calvarese" <jcc7 cox.net> wrote in message 
 news:d3ume6$2h3g$1 digitaldaemon.com...
 
Ben Hinkle wrote:
...


P.S. Anyone advise on how to get a clickable message link from an entry 
in Outlook Express? I know it's done, because some of you do it. :-)

That would be nice because I only know how to point to the forum page on the DigitalMars site and that only takes you to a particular message and not the thread.

If you go to http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D, and click on the "Subject" tab, you can see the message titles. Since they're alphabetized, the first page currently has entries for "" (no subject), "!(null is hkey) ??", and other subjects which begin with punctuation symbols. You'll probably need to click the "More" button a few times to get close to what you're looking for. (Is that what you want or did I answer the wrong question?)

I meant all I know how to do is this: digitalmars.D/6809 How can I get a link to the whole thread instead of just a message in the thread?

Oops, I misunderstood. I don't think I've seen anyone do that (maybe it doesn't work for me since I use Thunderbird). Would it show up in a newsreader or a web-browser? Or do you mean one of the archive pages, such as http://www.digitalmars.com/d/archives/digitalmars/D/13965.html? There's a separate main page for each newsgroup (but Walter hasn't run his update process in a while, so not all of the newsgroups even have a page yet): http://www.digitalmars.com/d/archives/digitalmars/D/index.html http://www.digitalmars.com/d/archives/digitalmars/D/dtl/index.html http://www.digitalmars.com/d/archives/digitalmars/D/bugs/index.html http://www.digitalmars.com/d/archives/D/gnu/index.html http://www.digitalmars.com/d/archives/index.html -- jcc7 http://jcc_7.tripod.com/d/
Apr 17 2005
parent reply Georg Wrede <georg.wrede nospam.org> writes:
J C Calvarese wrote:
 Ben Hinkle wrote:
 
 "J C Calvarese" <jcc7 cox.net> wrote in message 
 news:d3ume6$2h3g$1 digitaldaemon.com...
 
 Ben Hinkle wrote: ...
 
 
 P.S. Anyone advise on how to get a clickable message link
 from an entry in Outlook Express? I know it's done, because
 some of you do it. :-)

That would be nice because I only know how to point to the forum page on the DigitalMars site and that only takes you to a particular message and not the thread.

If you go to http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D, and click on the "Subject" tab, you can see the message titles. Since they're alphabetized, the first page currently has entries for "" (no subject), "!(null is hkey) ??", and other subjects which begin with punctuation symbols. You'll probably need to click the "More" button a few times to get close to what you're looking for. (Is that what you want or did I answer the wrong question?)

I meant all I know how to do is this: digitalmars.D/6809 How can I get a link to the whole thread instead of just a message in the thread?

Oops, I misunderstood. I don't think I've seen anyone do that (maybe it doesn't work for me since I use Thunderbird). Would it show up in a newsreader or a web-browser? Or do you mean one of the archive pages, such as http://www.digitalmars.com/d/archives/digitalmars/D/13965.html? There's a separate main page for each newsgroup (but Walter hasn't run his update process in a while, so not all of the newsgroups even have a page yet):

Man, we should collect money to give him a Linux box. ;-) They do stuff like that by themselves.
 http://www.digitalmars.com/d/archives/digitalmars/D/index.html 
 http://www.digitalmars.com/d/archives/digitalmars/D/dtl/index.html 
 http://www.digitalmars.com/d/archives/digitalmars/D/bugs/index.html 
 http://www.digitalmars.com/d/archives/D/gnu/index.html 
 http://www.digitalmars.com/d/archives/index.html
 

Apr 18 2005
parent reply "Ben Hinkle" <ben.hinkle gmail.com> writes:
 I meant all I know how to do is this: 
 digitalmars.D/6809 How
 can I get a link to the whole thread instead of just a message in the 
 thread?

Oops, I misunderstood. I don't think I've seen anyone do that (maybe it doesn't work for me since I use Thunderbird). Would it show up in a newsreader or a web-browser?


I agree - I don't think it is possible either, but I figured I'd ask since many people on this list can run a forum site in their sleep and might know a trick to get the thread link. I only mentioned it because Matthew innocently asked the question about how to get OE to produce links - which I don't know how to do either. When I want to reference a message I have to go fire up the dmd web site and find the message and grab the URL.
 Or do you mean one of the archive pages, such as 
 http://www.digitalmars.com/d/archives/digitalmars/D/13965.html?


no.
 There's a separate main page for each newsgroup (but Walter hasn't
 run his update process in a while, so not all of the newsgroups even
 have a page yet):

Man, we should collect money to give him a Linux box. ;-) They do stuff like that by themselves.

I already have a Linux box - or more accurately I made my Windows box dual-boot. I flip back and forth about my preferred boot system. Some months I wind up working on Linux more, sometimes Windows more.
 http://www.digitalmars.com/d/archives/digitalmars/D/index.html 
 http://www.digitalmars.com/d/archives/digitalmars/D/dtl/index.html 
 http://www.digitalmars.com/d/archives/digitalmars/D/bugs/index.html 
 http://www.digitalmars.com/d/archives/D/gnu/index.html 
 http://www.digitalmars.com/d/archives/index.html


yup. I'm aware of those. I often search them for reference links.
Apr 18 2005
next sibling parent reply Georg Wrede <georg.wrede nospam.org> writes:
Ben Hinkle wrote:
 There's a separate main page for each newsgroup (but Walter
 hasn't run his update process in a while, so not all of the
 newsgroups even have a page yet):

Man, we should collect money to give him a Linux box. ;-) They do stuff like that by themselves.

I already have a Linux box - or more accurately I made my Windows box dual-boot. I flip back and forth about my preferred boot system. Some months I wind up working on Linux more, sometimes Windows more.

I meant get a Linux box for Walter, so he didn't have to _remember_ to update the newsgroups every time. :-)
Apr 18 2005
next sibling parent J C Calvarese <jcc7 cox.net> writes:
Georg Wrede wrote:
 Ben Hinkle wrote:
 
 There's a separate main page for each newsgroup (but Walter
 hasn't run his update process in a while, so not all of the
 newsgroups even have a page yet):

Man, we should collect money to give him a Linux box. ;-) They do stuff like that by themselves.

I already have a Linux box - or more accurately I made my Windows box dual-boot. I flip back and forth about my preferred boot system. Some months I wind up working on Linux more, sometimes Windows more.

I meant get a Linux box for Walter, so he didn't have to _remember_ to update the newsgroups every time.

I don't expect Walter to update the archives every day, but once a month would be nice. ;)
 
 :-)

-- jcc7 http://jcc_7.tripod.com/d/
Apr 18 2005
prev sibling parent "Walter" <newshound digitalmars.com> writes:
"Georg Wrede" <georg.wrede nospam.org> wrote in message
news:4263B525.2090800 nospam.org...
 I meant get a Linux box for Walter, so he didn't have to _remember_ to
 update the newsgroups every time.

Jan and I have been talking about automating it a bit.
Apr 30 2005
prev sibling parent "Regan Heath" <regan netwin.co.nz> writes:
On Mon, 18 Apr 2005 08:51:47 -0400, Ben Hinkle <ben.hinkle gmail.com>  
wrote:
 I meant all I know how to do is this:
 digitalmars.D/6809 How
 can I get a link to the whole thread instead of just a message in the
 thread?

Oops, I misunderstood. I don't think I've seen anyone do that (maybe it doesn't work for me since I use Thunderbird). Would it show up in a newsreader or a web-browser?


I agree - I don't think it is possible either, but I figured I'd ask since many people on this list can run a forum site in their sleep and might know a trick to get the thread link. I only mentioned it because Matthew innocently asked the question about how to get OE to produce links - which I don't know how to do either. When I want to reference a message I have to go fire up the dmd web site and find the message and grab the URL.

I just grab the first part of the url i.e. http://www.digitalmars.com/drn-bin/wwwnews? add the newsgroup name digitalmars.D/ add the article id (I get this from the headers of the message I want to reference, i.e. your message to which I replied has "Xref: digitalmars.com digitalmars.D:21910" giving me digitalmars.D/21910 It would be nice if the client did all this work for me, it could do from "http://www.digitalmars.com/drn-bin/wwwnews?" and the Xref header. Regan
Apr 18 2005
prev sibling parent xs0 <xs0 xs0.com> writes:
 I think there are two (or more) proposals here. My idea doesn't 
 involve a particular interface, rather heterogeneity is supported as 
 a natural consequence of the requirement for all types in the array 
 (or whatever) to be related polymorphically.
 
 I'm pretty sure what I proposed in March - "A proposal for a new, 
 improved opCmp() [WAS: Round-up of the excuses for keeping 
 Object.opCmp, and rebuttals to them]" 
 (d0lsv5$1496$1 digitaldaemon.com) - still accurately represents my 
 thoughts.

I went and checked (btw, it would've been nice to mention that the thread started in September 2004 :) I see at least this problem:
 As it stands above, a heterogeneous array of instances of these types, 
 say [b1, b2, d1, md1, b3, md2, b4] would be sortable because Base 
 derives opCmp(). Moreover, it would be sorted solely by the 
 implementation of Base.opCmp() for all instances irrespective of their 
 actual type.

This means that either Base must know all its subclasses (which is like total crap), or that all subclasses must implement opCmp(Base), which is about the same as implementing opCmp(Object), its just a different base class. Furthermore, suppose I create a Number->[Int, Float] hierarchy and use it throughout my code. Later, I need to interface with some library, but that library has its own Num->[Integer, Double] hierarchy. I see no reason why they shouldn't be comparable, but they can't be, if there's no opCmp in Object.. xs0
Apr 15 2005
prev sibling parent reply "Kris" <fu bar.com> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote...
 "Sean Kelly" <sean f4.ca> wrote in message
 news:d3pqsk$1jsl$1 digitaldaemon.com...
 In article <d3pq4b$1jhe$1 digitaldaemon.com>, Ben Hinkle says...
I'd like to see a more complete description of what would change before
making up my mind. If we just remove Object.opCmp obviously many things
won't work (eg, aa's, sorting, dynamic array operations, maybe more) so
what
exactly won't work and what will have to change to get it to work?



large chunks of the TypeInfo system isn't trivial IMO. Maybe I'm just
being
thick but I'd like to see more details.

Moving the methods to interfaces *almost* works, and the changes really aren't too bad on the library side (I gave this a whirl with Ares--there's a branched version on my website if you're interested). But this approach also requires changes to portions of DMD that aren't shipped in source form, so estimating their scope is somewhat difficult. Maybe someone with GDC experience could chime in?

The interface would presumably be Comparable.opCmp(Comparable), correct?

Aye.
I thought the primary complaint against opCmp was that people would define

 class Foo with Foo.opCmp(Foo) and expect it to work.

I thought it was the fact that classes should not be Comparable by default, since it makes no sense to compare them if not explicitly supported. There's also the small issue of apparently being incompatable with a compacting-GC. Further, in the interests of robustness and correctness, there should be a compile-time error for attempts to compare an aggregate that does not explicitly implement opCmp(). The interface can potentially move opEquals() out of the root object also, such that it would be a compile-time error to apply '==' upon a class without an explicit opEquals() implementation. This makes for notably more robust code, as was discussed at length recently. We're talking about the root object here. It should be engineered in such a manner whereby it /prevents/ pedestrian faults. It should certainly not breed them :-) There are limitations using the interface approach; perhaps the main one is the method declaration, as you pointed out. The best overall suggestion I've heard so far was from Matthew ~ but that requires a change to the compiler. The interface approach would, on the surface, potentially work without any internal compiler changes. There's the tradeoff. - Kris
Apr 15 2005
parent "Ben Hinkle" <ben.hinkle gmail.com> writes:
I thought the primary complaint against opCmp was that people would define
 a class Foo with Foo.opCmp(Foo) and expect it to work.

I thought it was the fact that classes should not be Comparable by default, since it makes no sense to compare them if not explicitly supported.

Personally I have no problem with a default behavior if it has enough practical benefits. The debatable part is narrowed down to "enough", "practical" and "benefits". :-)
 There's also the small issue of apparently being incompatable with a 
 compacting-GC.

This one doesn't worry me too much because the GC and Object.opCmp are compiler-dependent - though I know Sean is working on a pluggable API for the GC. It would be nice to not have to worry about it at all.
 Further, in the interests of robustness and correctness, there should be a
 compile-time error for attempts to compare an aggregate that does not
 explicitly implement opCmp().

 The interface can potentially move opEquals() out of the root object also,
 such that it would be a compile-time error to apply '==' upon a class
 without an explicit opEquals() implementation. This makes for notably more
 robust code, as was discussed at length recently.

 We're talking about the root object here. It should be engineered in such 
 a
 manner whereby it /prevents/ pedestrian faults. It should certainly not
 breed them :-)

 There are limitations using the interface approach; perhaps the main one 
 is
 the method declaration, as you pointed out. The best overall suggestion 
 I've
 heard so far was from Matthew ~ but that requires a change to the 
 compiler.
 The interface approach would, on the surface, potentially work without any
 internal compiler changes. There's the tradeoff.

Presumably the TypeInfo for Object (ti_C.d) and arrays of objects (ti_AC.d) would try casting to Comparable and throw if it failed? That seems the most reasonable behavior. That way the code class Foo {} void main() { Foo[] x,y; x.length = 2; y.length = 2; x < y; } would compile but throw at run-time. The alternative would be to change how array comparison works more fundamentally. Similarly the AA implementation would have to change to not use the TypeInfo compare hook at all.
Apr 15 2005
prev sibling parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Ben Hinkle" <ben.hinkle gmail.com> wrote in message 
news:d3pq4b$1jhe$1 digitaldaemon.com...
 "Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message 
 news:d3pcr2$19r3$1 digitaldaemon.com...
 "Ben Hinkle" <bhinkle mathworks.com> wrote in message 
 news:d3p9qh$17hr$1 digitaldaemon.com...
 2. Leave the current DMD behaviour in, and document it 
 properly.

I would add 2a: leave it in, document it and add a warning to dmd and dlint for classes that define an opCmp that shadows Object.opCmp. In fact a general warnings about shadowing member functions in base classes should say "Foo.opCmp(Foo) shadows Object.opCmp(Object)". For the common case of Object.opCmp it should give a nicer warning that should say something like "Foo.opCmp(Foo) shadows Object.opCmp(Object). Consider defining Foo.opCmp(Object) for associative arrays, sorting and other uses".

But what's the attraction with addressing the symptoms of a disease, when we can prevent the disease? I'm not being sarcastic, I really want to know why people prefer this approach? Does it have _any_ advantages?

I'd like to see a more complete description of what would change before making up my mind. If we just remove Object.opCmp obviously many things won't work (eg, aa's, sorting, dynamic array operations, maybe more) so what exactly won't work and what will have to change to get it to work? Redoing large chunks of the TypeInfo system isn't trivial IMO. Maybe I'm just being thick but I'd like to see more details.

Not at all. It's a great idea. I myself have only a semi-rigorous idea of what's to be involved. Kris is, I think, the top expert on this topic. I think a proper discussion of what's involved is a great idea. Kris, do you want to kick it off?
Apr 15 2005
parent reply "Kris" <fu bar.com> writes:
"Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message
news:d3psf3$1l16$1 digitaldaemon.com...
 "Ben Hinkle" <ben.hinkle gmail.com> wrote in message
 news:d3pq4b$1jhe$1 digitaldaemon.com...
 "Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message
 news:d3pcr2$19r3$1 digitaldaemon.com...
 "Ben Hinkle" <bhinkle mathworks.com> wrote in message
 news:d3p9qh$17hr$1 digitaldaemon.com...
 2. Leave the current DMD behaviour in, and document it
 properly.

I would add 2a: leave it in, document it and add a warning to dmd and dlint for classes that define an opCmp that shadows Object.opCmp. In fact a general warnings about shadowing member functions in base classes should say "Foo.opCmp(Foo) shadows Object.opCmp(Object)". For the common case of Object.opCmp it should give a nicer warning that should say something like "Foo.opCmp(Foo) shadows Object.opCmp(Object). Consider defining Foo.opCmp(Object) for associative arrays, sorting and other uses".

But what's the attraction with addressing the symptoms of a disease, when we can prevent the disease? I'm not being sarcastic, I really want to know why people prefer this approach? Does it have _any_ advantages?

I'd like to see a more complete description of what would change before making up my mind. If we just remove Object.opCmp obviously many things won't work (eg, aa's, sorting, dynamic array operations, maybe more) so what exactly won't work and what will have to change to get it to work? Redoing large chunks of the TypeInfo system isn't trivial IMO. Maybe I'm just being thick but I'd like to see more details.

Not at all. It's a great idea. I myself have only a semi-rigorous idea of what's to be involved. Kris is, I think, the top expert on this topic.

? Yer arse!
 I think a proper discussion of what's involved is a great idea.

 Kris, do you want to kick it off?

Okay. Here we are again at Wibbly Stadium, where the vast crowd of -- two -- are anxious for the match to begin ... Ref blows his whistle! Match begins ~ Kris takes the centre-kick and ... passes the ball to Matthew! Seriously though. Sean just posted that he's actually tried the Interface approach with Ares, so I suggest we take this conversation over there instead. I'll happily weight in on the topic, but let's see what Sean has. BTW; as far as resolutions go, I fully agree with Matthew's (earlier) take on it. But the compiler would have to change for that to happen. If that's kosher, then whoopee. Otherwise we have to look for an alternate. What Sean is attempting appears to be one reasonable option.
Apr 15 2005
parent reply "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"Kris" <fu bar.com> wrote in message 
news:d3ptks$1lkj$1 digitaldaemon.com...
 "Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message
 news:d3psf3$1l16$1 digitaldaemon.com...
 "Ben Hinkle" <ben.hinkle gmail.com> wrote in message
 news:d3pq4b$1jhe$1 digitaldaemon.com...
 "Matthew" <admin stlsoft.dot.dot.dot.dot.org> wrote in message
 news:d3pcr2$19r3$1 digitaldaemon.com...
 "Ben Hinkle" <bhinkle mathworks.com> wrote in message
 news:d3p9qh$17hr$1 digitaldaemon.com...
 2. Leave the current DMD behaviour in, and document it
 properly.

I would add 2a: leave it in, document it and add a warning to dmd and dlint for classes that define an opCmp that shadows Object.opCmp. In fact a general warnings about shadowing member functions in base classes should say "Foo.opCmp(Foo) shadows Object.opCmp(Object)". For the common case of Object.opCmp it should give a nicer warning that should say something like "Foo.opCmp(Foo) shadows Object.opCmp(Object). Consider defining Foo.opCmp(Object) for associative arrays, sorting and other uses".

But what's the attraction with addressing the symptoms of a disease, when we can prevent the disease? I'm not being sarcastic, I really want to know why people prefer this approach? Does it have _any_ advantages?

I'd like to see a more complete description of what would change before making up my mind. If we just remove Object.opCmp obviously many things won't work (eg, aa's, sorting, dynamic array operations, maybe more) so what exactly won't work and what will have to change to get it to work? Redoing large chunks of the TypeInfo system isn't trivial IMO. Maybe I'm just being thick but I'd like to see more details.

Not at all. It's a great idea. I myself have only a semi-rigorous idea of what's to be involved. Kris is, I think, the top expert on this topic.

? Yer arse!
 I think a proper discussion of what's involved is a great idea.

 Kris, do you want to kick it off?

Okay. Here we are again at Wibbly Stadium, where the vast crowd of -- two -- are anxious for the match to begin ... Ref blows his whistle! Match begins ~ Kris takes the centre-kick and ... passes the ball to Matthew! Seriously though. Sean just posted that he's actually tried the Interface approach with Ares, so I suggest we take this conversation over there instead. I'll happily weight in on the topic, but let's see what Sean has. BTW; as far as resolutions go, I fully agree with Matthew's (earlier) take on it. But the compiler would have to change for that to happen. If that's kosher, then whoopee. Otherwise we have to look for an alternate. What Sean is attempting appears to be one reasonable option.

Before we get into this, and potentially waste many more hours on challenging, enlightening, but eventually fruitless debate, I want to hear from Walter as to his _feeling_ on how close we are to 1.0, and therefore how amenable he's going to be to making significant language changes at this point. Otherwise, we really are just spending time we don't have for nothing more than a couple of chapters of "Imperfect D". Walter, can you characterise your position? Specifically, 1. Do you believe that there are any "serious flaws" in the D specification as it stands? 2. If the answer is no, do you have a degree of certainty that is unlikely to be overridden by any observations any of us might make? 3. If the answer to either 1 or 2 is yes, do you nonetheless have a need to expedite 1.0 despite any/all such "major flaws"? Obviously, if we get (X, Yes, Y) or (X, Y, Yes), then there's no point having the debate.
Apr 15 2005
parent Georg Wrede <georg.wrede nospam.org> writes:
Matthew wrote:
 Walter, can you characterise your position? Specifically,
     1. Do you believe that there are any "serious flaws" in the D 
 specification as it stands?
     2. If the answer is no, do you have a degree of certainty that 
 is unlikely to be overridden by any observations any of us might 
 make?
     3. If the answer to either 1 or 2 is yes, do you nonetheless 
 have a need to expedite 1.0 despite any/all such "major flaws"?
 
 Obviously, if we get (X, Yes, Y) or (X, Y, Yes), then there's no 
 point having the debate.

You'd better ask Walter off-line. The chances of him finding your particular post (soon enough), may be slim. So, get the answer, and post it here, thanks.
Apr 17 2005