www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - idea: syntactic sugar for disallowed operations

reply "Jeroen van Bemmel" <someone somewhere.com> writes:
Instead of

class A
	{
	    int opCmp(Object o)
	    {
       assert(0);	// comparison makes no sense
       return 0;
	    }
	}

perhaps add syntax like:

class A {
  int opCmp( Object o ) disallowed; // or "fail" or "error" or ...
} 
Jun 07 2004
next sibling parent reply J C Calvarese <jcc7 cox.net> writes:
Jeroen van Bemmel wrote:

 Instead of
 
 class A
 	{
 	    int opCmp(Object o)
 	    {
        assert(0);	// comparison makes no sense
        return 0;
 	    }
 	}
 
 perhaps add syntax like:
 
 class A {
   int opCmp( Object o ) disallowed; // or "fail" or "error" or ...
 } 

Seems like too small of a difference to add a keyword. -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/
Jun 07 2004
parent reply "Jan-Eric Duden" <jeduden whisset.com> writes:
How about this:

class A
 {
private:
     int opCmp(Object o)
     {
        assert(0); // comparison makes no sense
        return 0;
     }
};


-- 
Jan-Eric Duden
"J C Calvarese" <jcc7 cox.net> wrote in message
news:ca3m7u$2tbk$2 digitaldaemon.com...
 Jeroen van Bemmel wrote:

 Instead of

 class A
 {
     int opCmp(Object o)
     {
        assert(0); // comparison makes no sense
        return 0;
     }
 }

 perhaps add syntax like:

 class A {
   int opCmp( Object o ) disallowed; // or "fail" or "error" or ...
 }

Seems like too small of a difference to add a keyword. -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/

Jun 08 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <ca3osv$11f$1 digitaldaemon.com>, Jan-Eric Duden says...
How about this:

class A
 {
private:
     int opCmp(Object o)
     {
        assert(0); // comparison makes no sense
        return 0;
     }

Der. You're right. I should have thought of that! Jill
Jun 08 2004
next sibling parent hellcatv hotmail.com writes:
private isn't *that* private though

I could call it accidentally from within my class or within the module even!


In article <ca3qiv$4lb$1 digitaldaemon.com>, Arcane Jill says...
In article <ca3osv$11f$1 digitaldaemon.com>, Jan-Eric Duden says...
How about this:

class A
 {
private:
     int opCmp(Object o)
     {
        assert(0); // comparison makes no sense
        return 0;
     }

Der. You're right. I should have thought of that! Jill

Jun 08 2004
prev sibling parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:ca3qiv$4lb$1 digitaldaemon.com...
 In article <ca3osv$11f$1 digitaldaemon.com>, Jan-Eric Duden says...
How about this:

class A
 {
private:
     int opCmp(Object o)
     {
        assert(0); // comparison makes no sense
        return 0;
     }

Der. You're right. I should have thought of that! Jill

But this isn't the same. This way we have a function that asserts, but the way Jeroen sugested it would be the same as if that function didn't exist.
Jun 08 2004
next sibling parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Ivan Senji" <ivan.senji public.srce.hr> wrote in message
news:ca3v5u$fcp$1 digitaldaemon.com...
 "Arcane Jill" <Arcane_member pathlink.com> wrote in message
 news:ca3qiv$4lb$1 digitaldaemon.com...
 In article <ca3osv$11f$1 digitaldaemon.com>, Jan-Eric Duden says...
How about this:

class A
 {
private:
     int opCmp(Object o)
     {
        assert(0); // comparison makes no sense
        return 0;
     }

Der. You're right. I should have thought of that! Jill

But this isn't the same. This way we have a function that asserts, but the way Jeroen sugested it would be the same as if that function didn't exist.

I meant to say that they are both compile time errors, but assert lets you call a function where "disallowed" doesn't.
Jun 08 2004
prev sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
Okay, if D works the same as C++, this should do the trick:

       private int opCmp(Object o); // with no definition

It now becomes a LINK-TIME error if you try to call the function. Link-time is maybe not quite as good as compile-time, but it's certainly better than run-time. Arcane Jill.
Jun 08 2004
prev sibling next sibling parent Derek Parnell <derek psych.ward> writes:
On Tue, 8 Jun 2004 08:07:28 +0200, Jeroen van Bemmel wrote:

 Instead of
 
 class A
 	{
 	    int opCmp(Object o)
 	    {
        assert(0);	// comparison makes no sense
        return 0;
 	    }
 	}
 
 perhaps add syntax like:
 
 class A {
   int opCmp( Object o ) disallowed; // or "fail" or "error" or ...
 }

So it becomes a compile-time error rather than a run-time error, right? -- Derek Melbourne, Australia 8/Jun/04 4:27:22 PM
Jun 07 2004
prev sibling next sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <ca3l2n$2rv1$1 digitaldaemon.com>, Jeroen van Bemmel says...

perhaps add syntax like:

class A {
  int opCmp( Object o ) disallowed; // or "fail" or "error" or ...
} 

Actually, this is a pretty neat idea. In general, you might want to say that a class B which subclasses class A might want to *remove* features which A offered (as opposed to adding them, which is the normal thing to do). Another example might be: A has a function serialize(), but B (which subclasses A) does not, so you want to somehow forbid b.serialize(). The normal way this is done is to override the disallowed function with a function which throws an exeption or asserts, but it would be nice to have another way. This isn't just syntactic sugar though. There are real compiler/performance benefits, in a manner similar to final. For example, given the situations described above, a compiler COULD detect:
       b.serialize()

or
       a < b

and give you a COMPILE-TIME error instead of a run-time error. That's not syntactic sugar, that's a feature. Basically, your "disallowed" keyword would mean: "We dont' implement this function, and if you try to call it, we don't want you to be forwarded to the superclass function either". Probably a nightmare to implement though. Arcane Jill
Jun 08 2004
parent reply Norbert Nemec <Norbert.Nemec gmx.de> writes:
Arcane Jill wrote:

 In article <ca3l2n$2rv1$1 digitaldaemon.com>, Jeroen van Bemmel says...
 
perhaps add syntax like:

class A {
  int opCmp( Object o ) disallowed; // or "fail" or "error" or ...
}

Actually, this is a pretty neat idea. In general, you might want to say that a class B which subclasses class A might want to *remove* features which A offered (as opposed to adding them, which is the normal thing to do). Another example might be: A has a function serialize(), but B (which subclasses A) does not, so you want to somehow forbid b.serialize(). The normal way this is done is to override the disallowed function with a function which throws an exeption or asserts, but it would be nice to have another way.

This goes completely contrary to all concepts of OO: Polymorphism and inheritance say that a subclass has all capabilities of the parent class. If you want to disallow a feature in a subclass, that is either a sign of lazyness of bad design. Sometimes, throwing an assert(0) may be feasible, but the compiler will never be able to handle that kind of "disallowing" at compile-time.
Jun 09 2004
next sibling parent reply Derek <derek psyc.ward> writes:
On Wed, 09 Jun 2004 12:52:13 +0200, Norbert Nemec wrote:

 Arcane Jill wrote:
 
 In article <ca3l2n$2rv1$1 digitaldaemon.com>, Jeroen van Bemmel says...
 
perhaps add syntax like:

class A {
  int opCmp( Object o ) disallowed; // or "fail" or "error" or ...
}

Actually, this is a pretty neat idea. In general, you might want to say that a class B which subclasses class A might want to *remove* features which A offered (as opposed to adding them, which is the normal thing to do). Another example might be: A has a function serialize(), but B (which subclasses A) does not, so you want to somehow forbid b.serialize(). The normal way this is done is to override the disallowed function with a function which throws an exeption or asserts, but it would be nice to have another way.

This goes completely contrary to all concepts of OO: Polymorphism and inheritance say that a subclass has all capabilities of the parent class. If you want to disallow a feature in a subclass, that is either a sign of lazyness of bad design. Sometimes, throwing an assert(0) may be feasible, but the compiler will never be able to handle that kind of "disallowing" at compile-time.

Norbert, are you saying that its okay for this type of thing to be a run-time error but not a compile-time error? Isn't that what the request is really about? That is, let's change this technique from a run-time test to one that is detected at compile-time instead. Let's say that somebody has written a Real Neat Class (RNC) that has a sorting method in it. Now I wish to create a new class based on this but sorting is not really sensible for it, so I wish to prevent the sort method from *ever* being used. Yes, I could write a sort method that caused a run-time effect (eg. throw an exception), or if we had a disable facility, to tell the compiler that I'm explictly disallowing any code to call the parent's sort method. I think that in principle, compile-time error detection is better than run-time detection. -- Derek Melbourne, Australia
Jun 09 2004
next sibling parent reply Norbert Nemec <Norbert.Nemec gmx.de> writes:
Derek wrote:

 Norbert,
 are you saying that its okay for this type of thing to be a run-time error
 but not a compile-time error? Isn't that what the request is really about?
 That is, let's change this technique from a run-time test to one that is
 detected at compile-time instead.
 
 Let's say that somebody has written a Real Neat Class (RNC) that has a
 sorting method in it. Now I wish to create a new class based on this but
 sorting is not really sensible for it, so I wish to prevent the sort
 method from *ever* being used. Yes, I could write a sort method that
 caused a run-time effect (eg. throw an exception), or if we had a disable
 facility, to tell the compiler that I'm explictly disallowing any code to
 call the parent's sort method.
 
 I think that in principle, compile-time error detection is better than
 run-time detection.

The last statement is true, but it this case cannot, in general, be detected at compile-time: -------- class A { void something() { do_something(); } } class B: A { void something() { assert(0); } } A a = new B(); a.something(); -------- Polymorphism means that an object of type B can be used via a type A reference. The compiler does not know what the reference points to. If you want to disable the function in the inheriting class, you are obviously working against polymorphism, i.e. you are abusing object-oriented tools (like inheritance) in some way, which I would call "faulty design".
Jun 09 2004
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Norbert Nemec wrote:
<snip>
 class A {
         void something() {
                 do_something();
         }
 }
 
 class B: A {
         void something() {
                 assert(0);
         }
 }
 
 A a = new B();
 a.something();
 --------
 
 Polymorphism means that an object of type B can be used via a type A
 reference. The compiler does not know what the reference points to. If you
 want to disable the function in the inheriting class, you are obviously
 working against polymorphism, i.e. you are abusing object-oriented tools
 (like inheritance) in some way, which I would call "faulty design".

Not to mention using it to indicate 'not yet implemented'.... Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jun 09 2004
prev sibling next sibling parent reply Andy Friesen <andy ikagames.com> writes:
Derek wrote:

 are you saying that its okay for this type of thing to be a run-time error
 but not a compile-time error? Isn't that what the request is really about?
 That is, let's change this technique from a run-time test to one that is
 detected at compile-time instead.
 
 Let's say that somebody has written a Real Neat Class (RNC) that has a
 sorting method in it. Now I wish to create a new class based on this but
 sorting is not really sensible for it, so I wish to prevent the sort method
 from *ever* being used. Yes, I could write a sort method that caused a
 run-time effect (eg. throw an exception), or if we had a disable facility,
 to tell the compiler that I'm explictly disallowing any code to call the
 parent's sort method.

Since your RealNeatSubclass is-a RealNeatClass, there's a problem if it be used any place a RNC is needed. Further, compile-time checking for this sort of thing will be incomplete at best. RNC rnc = new RealNeatSubclass(); if (rnc < otherRnc) // the compiler can't help you here Polymorphism can't be used to subtract behaviours from a class. (this is why Object mustn't define opCmp or opEquals, incidently) -- andy
Jun 09 2004
next sibling parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Andy Friesen" <andy ikagames.com> wrote in message
news:ca7gof$22p$1 digitaldaemon.com...
 Derek wrote:

 are you saying that its okay for this type of thing to be a run-time


 but not a compile-time error? Isn't that what the request is really


 That is, let's change this technique from a run-time test to one that is
 detected at compile-time instead.

 Let's say that somebody has written a Real Neat Class (RNC) that has a
 sorting method in it. Now I wish to create a new class based on this but
 sorting is not really sensible for it, so I wish to prevent the sort


 from *ever* being used. Yes, I could write a sort method that caused a
 run-time effect (eg. throw an exception), or if we had a disable


 to tell the compiler that I'm explictly disallowing any code to call the
 parent's sort method.

Since your RealNeatSubclass is-a RealNeatClass, there's a problem if it be used any place a RNC is needed. Further, compile-time checking for this sort of thing will be incomplete at best. RNC rnc = new RealNeatSubclass(); if (rnc < otherRnc) // the compiler can't help you here Polymorphism can't be used to subtract behaviours from a class. (this is why Object mustn't define opCmp or opEquals, incidently)

Why? You dodn't give any explanation why they must be defined!! You just said it. Please explain it to me, what does polymorphism have to do with opCmp and opEquals having to be in a class object. Why not opAdd and opShl_r?
   -- andy

Jun 09 2004
prev sibling parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Andy Friesen" <andy ikagames.com> wrote in message
news:ca7gof$22p$1 digitaldaemon.com...
 Derek wrote:

 are you saying that its okay for this type of thing to be a run-time


 but not a compile-time error? Isn't that what the request is really


 That is, let's change this technique from a run-time test to one that is
 detected at compile-time instead.

 Let's say that somebody has written a Real Neat Class (RNC) that has a
 sorting method in it. Now I wish to create a new class based on this but
 sorting is not really sensible for it, so I wish to prevent the sort


 from *ever* being used. Yes, I could write a sort method that caused a
 run-time effect (eg. throw an exception), or if we had a disable


 to tell the compiler that I'm explictly disallowing any code to call the
 parent's sort method.

Since your RealNeatSubclass is-a RealNeatClass, there's a problem if it be used any place a RNC is needed. Further, compile-time checking for this sort of thing will be incomplete at best. RNC rnc = new RealNeatSubclass(); if (rnc < otherRnc) // the compiler can't help you here Polymorphism can't be used to subtract behaviours from a class. (this is why Object mustn't define opCmp or opEquals, incidently)

SORRY! SORRY! SORRY! I read must :) I'am glad that there is atleast one person to agree with me on this. Great!
   -- andy

Jun 09 2004
parent reply "Marcello Gnani" <marcello_gnani tiscali.it> writes:
In article <ca7i8c$488$1 digitaldaemon.com>, Ivan Senji says...
"Andy Friesen" <andy ikagames.com> wrote in message
news:ca7gof$22p$1 digitaldaemon.com...
 Derek wrote:

 are you saying that its okay for this type of thing to be a run-time


 but not a compile-time error? Isn't that what the request is really


 That is, let's change this technique from a run-time test to one that is
 detected at compile-time instead.

 Let's say that somebody has written a Real Neat Class (RNC) that has a
 sorting method in it. Now I wish to create a new class based on this but
 sorting is not really sensible for it, so I wish to prevent the sort


 from *ever* being used. Yes, I could write a sort method that caused a
 run-time effect (eg. throw an exception), or if we had a disable


 to tell the compiler that I'm explictly disallowing any code to call the
 parent's sort method.

Since your RealNeatSubclass is-a RealNeatClass, there's a problem if it be used any place a RNC is needed. Further, compile-time checking for this sort of thing will be incomplete at best. RNC rnc = new RealNeatSubclass(); if (rnc < otherRnc) // the compiler can't help you here Polymorphism can't be used to subtract behaviours from a class.


I agree with Ivan Senji here; and even if it was possible, I think it would be unwise: in all OO languages I know, a derived class adds functionality to his base class. If one writes a generic algorithm based on functionalities (or a given functionality) of class A, I think it would be undesirable that algoritm to fail (or to be unavailable) for a class B derived from A, because B is-a A. If a given functionality of class A makes no sense for class B, I think it could be better to derive class B from a super class of A that does not have the non-sense functionality.
 (this is why Object mustn't define opCmp or opEquals, incidently)


I think I see the point: if Object defines opCmp or opEquals and object is the default super class, then (if what I just said holds) all classes will have these operators defined. So, what if, for a given class, opCmp or opEquals makes no sense? But I think allowing the de-powering of a super class is not the right answer; I think it would be better if D had a SuperObject class (as super class of Object). That SuperObject class should not have any specific functionality at all (no variables, functions or operators defined) and all classes that don't want some of the functionality of Object should be derived from SuperObject rather than from Object. Object could continue to be the default base class for all the classes that doesn't declare a base class explicitly, in order not to break actual code (and because I think most classes will need Object's functionality). This would allow building a class with less functionality than Object.
SORRY! SORRY! SORRY! I read must :)
I'am glad that there is atleast one person to agree with me on this.
Great!

   -- andy


Marcello Gnani
Jun 10 2004
parent "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Marcello Gnani" <marcello_gnani tiscali.it> wrote in message
news:ca9mge$ba0$1 digitaldaemon.com...
 In article <ca7i8c$488$1 digitaldaemon.com>, Ivan Senji says...
"Andy Friesen" <andy ikagames.com> wrote in message
news:ca7gof$22p$1 digitaldaemon.com...
 Derek wrote:

 are you saying that its okay for this type of thing to be a run-time


 but not a compile-time error? Isn't that what the request is really


 That is, let's change this technique from a run-time test to one that




 detected at compile-time instead.

 Let's say that somebody has written a Real Neat Class (RNC) that has




 sorting method in it. Now I wish to create a new class based on this




 sorting is not really sensible for it, so I wish to prevent the sort


 from *ever* being used. Yes, I could write a sort method that caused




 run-time effect (eg. throw an exception), or if we had a disable


 to tell the compiler that I'm explictly disallowing any code to call




 parent's sort method.

Since your RealNeatSubclass is-a RealNeatClass, there's a problem if it be used any place a RNC is needed. Further, compile-time checking for this sort of thing will be incomplete at best. RNC rnc = new RealNeatSubclass(); if (rnc < otherRnc) // the compiler can't help you here Polymorphism can't be used to subtract behaviours from a class.


I agree with Ivan Senji here; and even if it was possible, I think it

 unwise: in all OO languages I know, a derived class adds functionality to

 base class. If one writes a generic algorithm based on functionalities (or

 given functionality) of class A, I think it would be undesirable that

 to fail (or to be unavailable) for a class B derived from A, because B

 If a given functionality of class A makes no sense for class B, I think it

 be better to derive class B from a super class of A that does not have the
 non-sense functionality.

 (this is why Object mustn't define opCmp or opEquals, incidently)


I think I see the point: if Object defines opCmp or opEquals and object is

 default super class, then (if what I just said holds) all classes will

 these operators defined. So, what if, for a given class, opCmp or opEquals

 no sense?

That is exactly what is the problem.
 But I think allowing the de-powering of a super class is not the right

I at first thought why not, it seamed like a god idea to allow it but now i know it would be bad.
 think it would be better if D had a SuperObject class (as super class of
 Object). That SuperObject class should not have any specific functionality

Or even simpler just remove these two operators from object, and have a standard mixin that defines them so everyone has a choice to have them or not.
 all (no variables, functions or operators defined) and all classes that

 want some of the functionality of Object should be derived from

 rather than from Object. Object could continue to be the default base

 all the classes that doesn't declare a base class explicitly, in order not

 break actual code (and because I think most classes will need Object's
 functionality).

 This would allow building a class with less functionality than Object.

SORRY! SORRY! SORRY! I read must :)
I'am glad that there is atleast one person to agree with me on this.
Great!

   -- andy


Marcello Gnani

Jun 10 2004
prev sibling parent =?ISO-8859-1?Q?Julio_C=E9sar_Carrascal_Urquijo?= writes:
Derek wrote:
 Norbert,
 are you saying that its okay for this type of thing to be a run-time error
 but not a compile-time error? Isn't that what the request is really about?
 That is, let's change this technique from a run-time test to one that is
 detected at compile-time instead.
 
 Let's say that somebody has written a Real Neat Class (RNC) that has a
 sorting method in it. Now I wish to create a new class based on this but
 sorting is not really sensible for it, so I wish to prevent the sort method
 from *ever* being used. Yes, I could write a sort method that caused a
 run-time effect (eg. throw an exception), or if we had a disable facility,
 to tell the compiler that I'm explictly disallowing any code to call the
 parent's sort method.
 
 I think that in principle, compile-time error detection is better than
 run-time detection.
 

Maybe using the *deprecate* attribute? That's compile time. -- Julio CÚsar Carrascal Urquijo http://jcesar.f2o.org/
Jun 09 2004
prev sibling parent "Jeroen van Bemmel" <someone somewhere.com> writes:
Hi Norbert,

Theoretically you are right. The compiler won't be able to detect all cases 
of infringement at compile time, so it should still generate the assert(0) 
(and/or throw an exception) code that is currently suggested in the 
documentation.

However, my suggestion does not change the design of the code. It was 
already designed to effectively disallow the method in the subclass, all I 
do is make it explicit. Whether or not this feature should be recommended 
for general use, perhaps "avoid when possible". But in those cases where you 
would otherwise put 'assert(0); throw exception', well why not? It's 
syntactic sugar, in other words, shorthand for the code that's there now.


"Norbert Nemec" <Norbert.Nemec gmx.de> wrote in message 
news:ca6q4t$1vu1$2 digitaldaemon.com...
 Arcane Jill wrote:

 In article <ca3l2n$2rv1$1 digitaldaemon.com>, Jeroen van Bemmel says...

perhaps add syntax like:

class A {
  int opCmp( Object o ) disallowed; // or "fail" or "error" or ...
}

Actually, this is a pretty neat idea. In general, you might want to say that a class B which subclasses class A might want to *remove* features which A offered (as opposed to adding them, which is the normal thing to do). Another example might be: A has a function serialize(), but B (which subclasses A) does not, so you want to somehow forbid b.serialize(). The normal way this is done is to override the disallowed function with a function which throws an exeption or asserts, but it would be nice to have another way.

This goes completely contrary to all concepts of OO: Polymorphism and inheritance say that a subclass has all capabilities of the parent class. If you want to disallow a feature in a subclass, that is either a sign of lazyness of bad design. Sometimes, throwing an assert(0) may be feasible, but the compiler will never be able to handle that kind of "disallowing" at compile-time.

Jun 10 2004
prev sibling parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Jeroen van Bemmel" <someone somewhere.com> wrote in message
news:ca3l2n$2rv1$1 digitaldaemon.com...
 Instead of

 class A
 {
     int opCmp(Object o)
     {
        assert(0); // comparison makes no sense
        return 0;
     }
 }

 perhaps add syntax like:

 class A {
   int opCmp( Object o ) disallowed; // or "fail" or "error" or ...
 }

I thinks the problem would easilly go away if Object didn't have opCmp, then it would be a compile time error! I really think it is a bit strange that when i define a class there is automatically a opCmp defined doing address comparison. I write class A{} A a,b; a=new A(); b=new A(); and a<b and a==b are not compile time errors, but a code doing something else. Smels!
Jun 08 2004
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Ivan Senji wrote:

<snip>
 I thinks the problem would easilly go away if Object didn't have opCmp,
 then it would be a compile time error!

Yes, we should fix this wart. There's no point in inventing new language features to work around it. D/26144 digitalmars.D.bugs/105 Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jun 08 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <ca468u$r8t$1 digitaldaemon.com>, Stewart Gordon says...

Yes, we should fix this wart.  There's no point in inventing new 
language features to work around it.

How about this. opCmp stays in Object, but instead of returning an int, it returns one of these:
       enum CompareResult
       {
           LESS,
           EQUAL,
           GREATER,
           NOT_COMPARABLE
       }

The default implementation in Object returns CompareResult.NOT_COMPARABLE. That would make all objects essentially uncomparable UNLESS you overrode opCmp. As a beneficial side-effect, this would also enable you to REMOVE comparability in a derived class. For example, imagine we had a class Real that was comparable. You might want to derive a class Complex which was incomparable. With this scheme, you could do that. Jill
Jun 08 2004
next sibling parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:ca4b6r$130m$1 digitaldaemon.com...
 In article <ca468u$r8t$1 digitaldaemon.com>, Stewart Gordon says...

Yes, we should fix this wart.  There's no point in inventing new
language features to work around it.

How about this. opCmp stays in Object, but instead of returning an int, it returns one of these:
       enum CompareResult
       {
           LESS,
           EQUAL,
           GREATER,
           NOT_COMPARABLE
       }

The default implementation in Object returns CompareResult.NOT_COMPARABLE.

 would make all objects essentially uncomparable UNLESS you overrode opCmp.

 beneficial side-effect, this would also enable you to REMOVE comparability

 derived class. For example, imagine we had a class Real that was

 might want to derive a class Complex which was incomparable. With this

 you could do that.

As you could also with disallowed plus more things. opCmp isn't the only problem: there is also opEquals class A{} A a,b; a==b; //is legal and is same as a===b; What sencedoes this have? I don't understand it! If i wan't to compare for identity i will use === or is.
 Jill

Jun 08 2004
parent reply Mike Swieton <mike swieton.net> writes:
On Tue, 08 Jun 2004 14:49:23 +0200, Ivan Senji wrote:
 class A{}
 A a,b;
 
 a==b; //is legal and is same as
 a===b;
 
 What sencedoes this have? I don't understand it!
 If i wan't to compare for identity i will use === or is.

They are not equivalent. The default implementation of opEquals does an identity comparison, but it can be overridden for equality comparison. This is really necessary because it's in a language which uses reference semantics for classes and allows operator overloading. Mike Swieton __ In the end, we will remember not the words of our enemies, but the silence of our friends. - Martin Luther King, Jr.
Jun 08 2004
parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Mike Swieton" <mike swieton.net> wrote in message
news:pan.2004.06.08.14.36.15.590154 swieton.net...
 On Tue, 08 Jun 2004 14:49:23 +0200, Ivan Senji wrote:
 class A{}
 A a,b;

 a==b; //is legal and is same as
 a===b;

 What sencedoes this have? I don't understand it!
 If i wan't to compare for identity i will use === or is.

They are not equivalent. The default implementation of opEquals does an identity comparison, but it can be overridden for equality comparison.

Here is the point in the word CAN. If it isn't overridden then == and === are doing the same thing. This seams to me like a big problem. Let's say we have some kind of templetized container class (like set) that uses opEquals to compare objects. And the user uses set!(A) even though the class A doesn't implement opEquals! The user may have forgotton about it, and the code still works but not the way it should. Container uses identity comparison in opEquals and i doubt there are cases where someone would want this? Are there? with class A{} A a,b; a==b; should be a compile time bug. If i really waqnted to do identitiy check i would have used === as i should!
 really necessary because it's in a language which uses reference semantics

 classes and allows operator overloading.

Can you please explain why is opEquals necessary to be in object? Maybe there is something i am missing.
 Mike Swieton
 __
 In the end, we will remember not the words of our enemies, but the silence

 our friends.
 - Martin Luther King, Jr.

Jun 08 2004
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Ivan Senji wrote:
<snip>
 This is
 
 Here is the point in the word CAN. If it isn't overridden then == and 
 === are doing the same thing. This seams to me like a big problem.
 
 Let's say we have some kind  of templetized container class (like 
 set) that uses opEquals to compare objects. And the user uses set!(A) 
 even though the class A doesn't implement opEquals! The user may have 
 forgotton about it, and the code still works but not the way it 
 should. Container uses identity comparison in opEquals and i doubt 
 there are cases where someone would want this? Are there?

<snip> There are probably plenty of classes of which two instances cannot be equal in any meaningful sense. For these, it only makes sense to compare the object references. So it provides this default behaviour. Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jun 08 2004
parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message
news:ca4vc7$27sg$1 digitaldaemon.com...
 Ivan Senji wrote:
 <snip>
 This is

 Here is the point in the word CAN. If it isn't overridden then == and
 === are doing the same thing. This seams to me like a big problem.

 Let's say we have some kind  of templetized container class (like
 set) that uses opEquals to compare objects. And the user uses set!(A)
 even though the class A doesn't implement opEquals! The user may have
 forgotton about it, and the code still works but not the way it
 should. Container uses identity comparison in opEquals and i doubt
 there are cases where someone would want this? Are there?

<snip> There are probably plenty of classes of which two instances cannot be equal in any meaningful sense. For these, it only makes sense to compare the object references. So it provides this default behaviour.

Exactly! But we are obviously thinking from the oposite sides :) If 2 instances of a class cannot be compared i wan't a==b to be illegal! What is === or "is" for? It is there to compare references to instances for identity. I don't believe there can be a default behaviour for == for classes that can't be compared!
 Stewart.

 --
 My e-mail is valid but not my primary mailbox, aside from its being the
 unfortunate victim of intensive mail-bombing at the moment.  Please keep
 replies on the 'group where everyone may benefit.

Jun 08 2004
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Ivan Senji wrote:
<snip>
 There are probably plenty of classes of which two instances cannot be 
 equal in any meaningful sense.  For these, it only makes sense to 
 compare the object references.  So it provides this default behaviour.

Exactly! But we are obviously thinking from the oposite sides :) If 2 instances of a class cannot be compared i wan't a==b to be illegal! What is === or "is" for? It is there to compare references to instances for identity. I don't believe there can be a default behaviour for == for classes that can't be compared!

They can be compared. They just compare unequal if they're not the same object. This enables them to be used in container templates for such things as keys and searching. There's no reason I can see for a class designer's wanting to prevent all users of the class from doing this. Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jun 09 2004
parent reply "Ivan Senji" <ivan.senji public.srce.hr> writes:
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message
news:ca6l6r$1pkv$1 digitaldaemon.com...
 Ivan Senji wrote:
 <snip>
 There are probably plenty of classes of which two instances cannot be
 equal in any meaningful sense.  For these, it only makes sense to
 compare the object references.  So it provides this default behaviour.

Exactly! But we are obviously thinking from the oposite sides :) If 2 instances of a class cannot be compared i wan't a==b to be illegal! What is === or "is" for? It is there to compare references to instances for identity. I don't believe there can be a default


 for == for classes that can't be compared!

They can be compared. They just compare unequal if they're not the same object.

And again IMHO that is what === is for.
 This enables them to be used in container templates for such things as
 keys and searching.  There's no reason I can see for a class designer's
 wanting to prevent all users of the class from doing this.

Doing what? Comparing for identity? I would prefer that a class that hasn't got these operators defined can't be used in such containers because if the author didn't implement these operators maybe ha was trying to say that it makes no sense. This causes problems when someone forgets to implement them and default version is used. This is a good example of what a standard mixin could be. If you wanted the default strange behavior you just do: class A { mixnin opEqualsAndCmp(); //... } If nothing comes from these discussion i would like to make a feature request <ironic> to implement opAdd in object, that calculates the sum of adresses of the 2 added objects...</ironic> :) By the way, noone has answered to me: Does anyones code depend on this strange feature? Are there any good reasons (not solvable by mixins) for defending this?
 Stewart.

 --
 My e-mail is valid but not my primary mailbox, aside from its being the
 unfortunate victim of intensive mail-bombing at the moment.  Please keep
 replies on the 'group where everyone may benefit.

Jun 09 2004
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Ivan Senji wrote:
<snip>
 This enables them to be used in container templates for such things as
 keys and searching.  There's no reason I can see for a class designer's
 wanting to prevent all users of the class from doing this.

Doing what? Comparing for identity? I would prefer that a class that hasn't got these operators defined can't be used in such containers because if the author didn't implement these operators maybe ha was trying to say that it makes no sense.

No. Ha was saying that only one instance of the class can conceivably have the same value. Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jun 09 2004
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Arcane Jill wrote:

<snip>
 The default implementation in Object returns CompareResult.NOT_COMPARABLE. That
 would make all objects essentially uncomparable UNLESS you overrode opCmp. As a
 beneficial side-effect, this would also enable you to REMOVE comparability in a
 derived class. For example, imagine we had a class Real that was comparable.
You
 might want to derive a class Complex which was incomparable. With this scheme,
 you could do that.

A complex number isn't a kind of real number. An array of reals is exactly that - an array of reals. Reals being comparable makes it possible to do such things as sort and binary search. If there is the odd complex number mixed in, then it isn't an array of reals anymore, even if the declaration confusingly says it is. Subclasses are supposed to extend functionality, not remove functionality. Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jun 08 2004
parent Norbert Nemec <Norbert.Nemec gmx.de> writes:
Stewart Gordon wrote:

 Arcane Jill wrote:
 
 <snip>
 The default implementation in Object returns
 CompareResult.NOT_COMPARABLE. That would make all objects essentially
 uncomparable UNLESS you overrode opCmp. As a beneficial side-effect, this
 would also enable you to REMOVE comparability in a derived class. For
 example, imagine we had a class Real that was comparable. You might want
 to derive a class Complex which was incomparable. With this scheme, you
 could do that.

A complex number isn't a kind of real number. An array of reals is exactly that - an array of reals. Reals being comparable makes it possible to do such things as sort and binary search. If there is the odd complex number mixed in, then it isn't an array of reals anymore, even if the declaration confusingly says it is. Subclasses are supposed to extend functionality, not remove functionality.

True. Interestingly: subclassing in OO programming is very similar to taking a subset in mathematics. real is a subset of complex. This subset is not closed under operations like sqrt, but as a subset of complex, real numbers offer everything complex number offer, and even more (like comparing). For class design, this relation is not very practical: It would not make much sense to derive real from a complex class, but from the mathematics point of view, that would be the correct way to do it.
Jun 09 2004