August 07, 2004
"Jarrett Billingsley" <kb3ctd2@yahoo.com> wrote in message news:cf2qfj$1toe$1@digitaldaemon.com...
> personally i don't see what's wrong with
> operator+() , but oh well.

operator+ doesn't work when you need both the forward and the 'r' versions of an operator overload. Also, opCmp handles <, <=, >, >=. And lastly, opCmp is eminently greppable.


August 07, 2004
[snip]

> The wost part is what exactly Object's behaviour is: the default opCmp effectively generates a random number for each object, and yields a comparison between those.

The random number is unique to the object. Think of it an an ID - kindof like a Social Security Number for objects. The problem I see with the current behavior is the impact it has on the GC architecture. Maybe the way out of that one is to have a marker interface called MovableObject that tells the GC an object can be moved - or something like that.

[snip]

> All it would take, as far as I can tell, is to change TypeInfoClass to compare hash codes instead of calling opCmp and opEquals.

[snip]

The problem is that two distinct objects (by any measurement) can have the
same hash code.


August 07, 2004
In article <cf2cs6$1p49$1@digitaldaemon.com>, Ivan Senji says...

>    int opCmp(Object o);
>    int opEquals(Object o);

I tend to think about things in mathematical terms, and in math, everything can be compared for equality, but not for less than. That is, for all x in U (the Universal Set), x = x.

Put more simply, everything equals itself. So an equality test makes sense for everything.

However, less than and greater than /don't/ make sense for everything (in math).
You cannot, for example, assign a truth value to the sentence "Wednesday is less
than Sunday". It doesn't make sense. Nor does ((3+4i) < (4+3i)). Matrices,
vectors, symmetry groups, functions, etc., etc., (the list is endless) do not
impose a complete ordering on their elements, and therefore < and > are
mathematically (rightly) undefined for those sets.

In D, every class is derived from Object, so every class inherits opCmp() - and this is nonsense. Suppose I write a class Weekday, or a class Complex, or Vector, or Matrix. These classes should /not/ allow expressions like (x < y) to compile.

So, from an inheritance point of view, the problem is not that opCmp() is bad, it's that it's not, actually, a property of /everything/. It's only a property of /some/ things.

There's a basic principle of polymorphism. Derived classes are supposed to /add/
functions, not remove them. If class A has a function f(), then polymorphism
says that class B (which derives from A) must also have a function f().
Similarly, if Object has a function opCmp(), then polymorphism says that Matrix
(which derives from Object) must also have a function opCmp(). BUT - the
elements of the set of all matrices are not ordered, so opCmp() makes no sense
for a matrix.

Walter advises us to override opCmp() in these cases, and to throw an exception in the implementation. That sucks. But more than that, this "solution" would prevent such objects (Matrices etc) from ever being stored in an associative array. That sucks even more.

But we /can/ have our cake and eat it. [SUGGESTION:] Associative arrays don't
need opCmp(). Honestly, they don't. Why not? - because the only thing AAs
require is a sort criterion. That sort criterion does not have to be based on <.
The current implementation of AAs is to sort based on (x < y), but then to have
Object define < such that (x < y) is implemented as (&x < &y). So why not just
have the sort criterion for AAs be (&x < &y) instead of (x < y)? If this were
so, Object wouldn't need <, everything would still work, < and > would still be
defined for those objects which /explicitly/ defined opCmp(), and everyone would
be happy.

Arcane Jill

PS. Actually, I retract "everyone would be happy". (If only making everyone happy were that easy). It's still a workable suggestion though.


August 07, 2004
Another workable solution is to remove AA's from the language syntax altogether; then the fundamental opCmp() requirement goes away. For all their initially perceived value, the AA baggage affects the core language in a number of detrimental ways. This would not be the case if AA's were a (replaceable & extensible) library module.


"Arcane Jill" <Arcane_member@pathlink.com> wrote in message news:cf3dst$28kb$1@digitaldaemon.com...
> In article <cf2cs6$1p49$1@digitaldaemon.com>, Ivan Senji says...
>
> >    int opCmp(Object o);
> >    int opEquals(Object o);
>
> I tend to think about things in mathematical terms, and in math,
everything can
> be compared for equality, but not for less than. That is, for all x in U
(the
> Universal Set), x = x.
>
> Put more simply, everything equals itself. So an equality test makes sense
for
> everything.
>
> However, less than and greater than /don't/ make sense for everything (in
math).
> You cannot, for example, assign a truth value to the sentence "Wednesday
is less
> than Sunday". It doesn't make sense. Nor does ((3+4i) < (4+3i)). Matrices,
> vectors, symmetry groups, functions, etc., etc., (the list is endless) do
not
> impose a complete ordering on their elements, and therefore < and > are mathematically (rightly) undefined for those sets.
>
> In D, every class is derived from Object, so every class inherits
opCmp() - and
> this is nonsense. Suppose I write a class Weekday, or a class Complex, or Vector, or Matrix. These classes should /not/ allow expressions like (x <
y) to
> compile.
>
> So, from an inheritance point of view, the problem is not that opCmp() is
bad,
> it's that it's not, actually, a property of /everything/. It's only a
property
> of /some/ things.
>
> There's a basic principle of polymorphism. Derived classes are supposed to
/add/
> functions, not remove them. If class A has a function f(), then
polymorphism
> says that class B (which derives from A) must also have a function f().
> Similarly, if Object has a function opCmp(), then polymorphism says that
Matrix
> (which derives from Object) must also have a function opCmp(). BUT - the
> elements of the set of all matrices are not ordered, so opCmp() makes no
sense
> for a matrix.
>
> Walter advises us to override opCmp() in these cases, and to throw an
exception
> in the implementation. That sucks. But more than that, this "solution"
would
> prevent such objects (Matrices etc) from ever being stored in an
associative
> array. That sucks even more.
>
> But we /can/ have our cake and eat it. [SUGGESTION:] Associative arrays
don't
> need opCmp(). Honestly, they don't. Why not? - because the only thing AAs require is a sort criterion. That sort criterion does not have to be based
on <.
> The current implementation of AAs is to sort based on (x < y), but then to
have
> Object define < such that (x < y) is implemented as (&x < &y). So why not
just
> have the sort criterion for AAs be (&x < &y) instead of (x < y)? If this
were
> so, Object wouldn't need <, everything would still work, < and > would
still be
> defined for those objects which /explicitly/ defined opCmp(), and everyone
would
> be happy.
>
> Arcane Jill
>
> PS. Actually, I retract "everyone would be happy". (If only making
everyone
> happy were that easy). It's still a workable suggestion though.
>
>


August 07, 2004
Arcane Jill wrote:
> In article <cf2cs6$1p49$1@digitaldaemon.com>, Ivan Senji says...
> 
> 
>>   int opCmp(Object o);
>>   int opEquals(Object o);
> 
> 
> I tend to think about things in mathematical terms, and in math, everything can
> be compared for equality, but not for less than. That is, for all x in U (the
> Universal Set), x = x.
> 
> Put more simply, everything equals itself. So an equality test makes sense for
> everything.
> 
> However, less than and greater than /don't/ make sense for everything (in math).
> You cannot, for example, assign a truth value to the sentence "Wednesday is less
> than Sunday". It doesn't make sense. Nor does ((3+4i) < (4+3i)). Matrices,
> vectors, symmetry groups, functions, etc., etc., (the list is endless) do not
> impose a complete ordering on their elements, and therefore < and > are
> mathematically (rightly) undefined for those sets.
> 
> In D, every class is derived from Object, so every class inherits opCmp() - and
> this is nonsense. Suppose I write a class Weekday, or a class Complex, or
> Vector, or Matrix. These classes should /not/ allow expressions like (x < y) to
> compile.
> 
> So, from an inheritance point of view, the problem is not that opCmp() is bad,
> it's that it's not, actually, a property of /everything/. It's only a property
> of /some/ things.
> 
> There's a basic principle of polymorphism. Derived classes are supposed to /add/
> functions, not remove them. If class A has a function f(), then polymorphism
> says that class B (which derives from A) must also have a function f().
> Similarly, if Object has a function opCmp(), then polymorphism says that Matrix
> (which derives from Object) must also have a function opCmp(). BUT - the
> elements of the set of all matrices are not ordered, so opCmp() makes no sense
> for a matrix.
> 
> Walter advises us to override opCmp() in these cases, and to throw an exception
> in the implementation. That sucks. But more than that, this "solution" would
> prevent such objects (Matrices etc) from ever being stored in an associative
> array. That sucks even more.
> 
> But we /can/ have our cake and eat it. [SUGGESTION:] Associative arrays don't
> need opCmp(). Honestly, they don't. Why not? - because the only thing AAs
> require is a sort criterion. That sort criterion does not have to be based on <.
> The current implementation of AAs is to sort based on (x < y), but then to have
> Object define < such that (x < y) is implemented as (&x < &y). So why not just
> have the sort criterion for AAs be (&x < &y) instead of (x < y)? If this were
> so, Object wouldn't need <, everything would still work, < and > would still be
> defined for those objects which /explicitly/ defined opCmp(), and everyone would
> be happy.

Right!  But there's still two kinks.  One is easy, the other is harder.

The easy one is dealing with a potentially compacting garbage collector.  &x < &y isn't so reliable if the collector decides to shuffle things around.  As promised, though, this is easy: use x.toHash() < y.toHash().

The hard one is that arrays have that built-in sort property.

Personally, I think we could just dump it and be done with it.  Back before D grew the respectable template mechanism we know and love today, building this into the language made perfect sense, but now that we do, it's cruft.  We don't need a built-in sort now that we can easily implement a good one using a template.

Failing that, the compiler could always use do a search on the array element type to determine whether it has an opCmp method and generate code accordingly (potentially ugly to implement, but completely seamless to the programmer), or define a 'special' interface ('Comparable' or somesuch) and only provide sorting functionality to classes which implement it.

 -- andy
August 07, 2004
Arcane Jill wrote:

> There's a basic principle of polymorphism. Derived classes are supposed to /add/
> functions, not remove them. 

Well, Eiffel (which seems to be the most complete OO-language I've seen) allow you to change *everything*, even removal. Neither Java nor C++ should define OOP nor polymorphism (IMHO), although I feel most comfortable with those two languages myself.

Lars Ivar Igesund
August 07, 2004
"Arcane Jill" <Arcane_member@pathlink.com> wrote in message news:cf3dst$28kb$1@digitaldaemon.com...
> In article <cf2cs6$1p49$1@digitaldaemon.com>, Ivan Senji says...
>
> >    int opCmp(Object o);
> >    int opEquals(Object o);
>
> I tend to think about things in mathematical terms, and in math,
everything can
> be compared for equality, but not for less than. That is, for all x in U
(the
> Universal Set), x = x.
>
> Put more simply, everything equals itself. So an equality test makes sense
for
> everything.

Isn't this identity? x === x ?
That is what we have a great seperate operator === and !== for.
Why should we also have == be defined by default to do the same as ===.
Ridicolous!


> However, less than and greater than /don't/ make sense for everything (in
math).
> You cannot, for example, assign a truth value to the sentence "Wednesday
is less
> than Sunday". It doesn't make sense. Nor does ((3+4i) < (4+3i)). Matrices,
> vectors, symmetry groups, functions, etc., etc., (the list is endless) do
not
> impose a complete ordering on their elements, and therefore < and > are mathematically (rightly) undefined for those sets.
>
> In D, every class is derived from Object, so every class inherits
opCmp() - and
> this is nonsense. Suppose I write a class Weekday, or a class Complex, or Vector, or Matrix. These classes should /not/ allow expressions like (x <
y) to
> compile.
>
> So, from an inheritance point of view, the problem is not that opCmp() is
bad,
> it's that it's not, actually, a property of /everything/. It's only a
property
> of /some/ things.

Great, now not only Andy Friesen agrees on this with me but even you (at
least in some part)
:)

> There's a basic principle of polymorphism. Derived classes are supposed to
/add/
> functions, not remove them. If class A has a function f(), then
polymorphism
> says that class B (which derives from A) must also have a function f().
> Similarly, if Object has a function opCmp(), then polymorphism says that
Matrix
> (which derives from Object) must also have a function opCmp(). BUT - the
> elements of the set of all matrices are not ordered, so opCmp() makes no
sense
> for a matrix.
>
> Walter advises us to override opCmp() in these cases, and to throw an
exception
> in the implementation. That sucks. But more than that, this "solution"
would
> prevent such objects (Matrices etc) from ever being stored in an
associative
> array. That sucks even more.
>
> But we /can/ have our cake and eat it. [SUGGESTION:] Associative arrays
don't
> need opCmp(). Honestly, they don't. Why not? - because the only thing AAs require is a sort criterion. That sort criterion does not have to be based
on <.
> The current implementation of AAs is to sort based on (x < y), but then to
have
> Object define < such that (x < y) is implemented as (&x < &y). So why not
just
> have the sort criterion for AAs be (&x < &y) instead of (x < y)? If this
were
> so, Object wouldn't need <, everything would still work, < and > would
still be
> defined for those objects which /explicitly/ defined opCmp(), and everyone
would
> be happy.

I would be perfectly happy with AAs requiring opCmp. But a compiler should
be smart
enough (and i Know that W could do this) to generate an error message if a
class
that doesn't define opCmp is used as a key.

so

class A{}
int[A] xy;

would generate: A cannot be a key of AA (missing opCmp) in line (someline)

It is much better than being able to have "class A{}" as a key but with
instances
of A magically sorted by their adresses wich is ofcourse ridicolous(again)!


> Arcane Jill
>
> PS. Actually, I retract "everyone would be happy". (If only making
everyone
> happy were that easy). It's still a workable suggestion though.

Impossible! :) (i mean making everyone happy)





August 07, 2004
"Andy Friesen" <andy@ikagames.com> wrote in message news:cf2s0k$1uu5$1@digitaldaemon.com...
> Ivan Senji wrote:
>
> > Isn't it time to get rid of them?
>
> Yes.

I'm glad that someone agrees with me on this. Maybe if we are boring enough we can convince others. :)

> Anything Object defines, *everything* defines, and, when it's something as broad as this, it sucks.
>
> The wost part is what exactly Object's behaviour is: the default opCmp effectively generates a random number for each object, and yields a comparison between those.  If this isn't abuse of overloaded operators, what is?
>
> All it would take, as far as I can tell, is to change TypeInfoClass to compare hash codes instead of calling opCmp and opEquals.  Lucky for us, this means that Object can still be sorted in an array and used as an AA key while making comparison operators raise a compile time error. Everybody wins.
>
> If nothing else, this would go a huge way toward disambiguating == and != from === and !==.  Using the former on most object references would be a compile error.
>
>   -- andy


August 07, 2004
"Walter" <newshound@digitalmars.com> wrote in message news:cf31k5$223l$1@digitaldaemon.com...
>
> "Ivan Senji" <ivan.senji@public.srce.hr> wrote in message news:cf2ibj$1qnr$1@digitaldaemon.com...
> > And additionally i may wan't my class objects to be incomparable, and this is not possible now.
>
> Just put an assert(0) in the opCmp() overload for your class.

This isn't right!
If i don't write opCmp i have opCmp,
If i don't wan't to have opCmp i have to write one!

What is so special about opCmp, (ok it is used in AAs but couldn't compiler report: "this type cann't be used in AA because of the missing opCmp!")

I know everyone would agree that it would be stupid if we had to write:

A opAdd(A a){assert(0);}
to make are type un-addable!

opCmp shouldn't be discriminated this way! :)


August 07, 2004
Ivan Senji wrote:

> opCmp shouldn't be discriminated this way! :)

Ivan's correct. You got my vote.

Lars Ivar Igesund