Thread overview
opLess and opGreater
May 07, 2004
Patrick Horn
May 07, 2004
Derek Parnell
May 07, 2004
Derek
May 07, 2004
J Anderson
May 07, 2004
Norbert Nemec
May 07, 2004
J Anderson
May 07, 2004
Stewart Gordon
May 10, 2004
Ilya Minkov
May 07, 2004
Currently in D there is a opCmp function returning a -1 if less, 0 if equal or 1 if greater.  But this does not apply to classes where there the less or greater doesn't strictly return True or False.

Consider a class for a 3-dimensional mathematical Vector.
class vector {
double i,j,k
..
}

In this class, for two vectors a and b, comparing a < b does not work because
vectors can be both greater and less (a.i<b.i but a.j>b.j)
But the problem is that opCmp can only return 1, -1 or 0, but nothing in
between. opCmp *must* return an int to work, because the compiler must return a
boolean to the expression (a>b). Therefore, this function would be invalid:

vector opCmp (vector b) {
return vector((i>b.i)?1:((i<b.i)?-1:0), (j>b.j)?1:((j<b.j)?-1:0),
(k>b.k)?1:((k<b.k)?-1:0));
}


The solution would be to have a method such as:

vector opGreater (vector b) {
return vector(i>b.i, j>b.j, k>b.k);
}

But D should still support opCmp because it is correct in most cases.

So to support both, the compiler should parse (a>b) and call a.opGreater(b).
The Object.opGreater method would then return (a.opCmp(b)==1).

Then, if the class overloads opGreater, the compiler will use that one instead and ignore opCmp for that class.


May 07, 2004
On Fri, 7 May 2004 06:52:53 +0000 (UTC), Patrick Horn wrote:

> Currently in D there is a opCmp function returning a -1 if less, 0 if equal or 1 if greater.  But this does not apply to classes where there the less or greater doesn't strictly return True or False.
> 
> Consider a class for a 3-dimensional mathematical Vector.
> class vector {
> double i,j,k
> ..
> }
> 
> In this class, for two vectors a and b, comparing a < b does not work because
> vectors can be both greater and less (a.i<b.i but a.j>b.j)
> But the problem is that opCmp can only return 1, -1 or 0, but nothing in
> between. opCmp *must* return an int to work, because the compiler must return a
> boolean to the expression (a>b). Therefore, this function would be invalid:
> 
> vector opCmp (vector b) {
> return vector((i>b.i)?1:((i<b.i)?-1:0), (j>b.j)?1:((j<b.j)?-1:0),
> (k>b.k)?1:((k<b.k)?-1:0));
> }
> 
> The solution would be to have a method such as:
> 
> vector opGreater (vector b) {
> return vector(i>b.i, j>b.j, k>b.k);
> }
> 
> But D should still support opCmp because it is correct in most cases.
> 
> So to support both, the compiler should parse (a>b) and call a.opGreater(b).
> The Object.opGreater method would then return (a.opCmp(b)==1).
> 
> Then, if the class overloads opGreater, the compiler will use that one instead and ignore opCmp for that class.

If I understand what you are saying, it is that given two vectors 'a' and 'b', then 'a' is said to be greater than 'b' if every element in 'a' is greater than the corresponding element 'b'. And similarly for "less than" and "equal to" tests. And so in the cases where there is a mixture of comparisions ( eg. a[1] < b[1] and a[2] > b[2]) you can't use a simple opCmp() result.

You might have to resort to this sort of thing...

  // WARNING; code not tested, just indicative code only.
  Vector a,b,c
  Vector gtVector = new Vector(1,1,1)
  Vector ltVector = new Vector(-1,-1,-1)
  Vector eqVector = new Vector(0,0,0)
  . . .
  c = (a > b);
  switch (c)
  {
   case gtVector:
    // do Greater-Than processing
     break;
   case ltVector:
    // do LessThan processing
    break;
   case eqVector:
    // do Equality processing
    break;
   default:
    // do mixed processing
    break;
  };

-- 
Derek
7/May/04 5:43:26 PM
May 07, 2004
In the operator overloading was designed with the clear objective that operators should only used with certain semantics and not, like in C++, abused for all kinds of purposes.

Using "less than" and "greater than" on vectors clearly is a border case to that. Currently these operators are meant to be used on for totally ordered sets (like real numbers etc.).

Extending them to be used on partially ordered sets (like vectors or complex numbers) would certainly possible. Either by introducing opLess and opGreater, or, even easier: by allowing opCmp to return values different from {-1,0,1} to designate "neither of the three".

Anyhow: in most cases, there is no general way to define a partial ordering. Like for your vectors: you propose to call one vector "greater than" another one comparing them element-wise, which is a legal partial ordering. Someone else might rather compare their absolute value, which is a different ordering which is just as reasonable.

For this reason, I believe it would not be a good idea to define a opCmp for two vectors at all, but rather to define some named routine that clearly says in which way you want to compare the two.



Patrick Horn wrote:

> Currently in D there is a opCmp function returning a -1 if less, 0 if
> equal or 1
> if greater.  But this does not apply to classes where there the less or
> greater doesn't strictly return True or False.
> 
> Consider a class for a 3-dimensional mathematical Vector.
> class vector {
> double i,j,k
> ..
> }
> 
> In this class, for two vectors a and b, comparing a < b does not work
> because vectors can be both greater and less (a.i<b.i but a.j>b.j)
> But the problem is that opCmp can only return 1, -1 or 0, but nothing in
> between. opCmp *must* return an int to work, because the compiler must
> return a boolean to the expression (a>b). Therefore, this function would
> be invalid:
> 
> vector opCmp (vector b) {
> return vector((i>b.i)?1:((i<b.i)?-1:0), (j>b.j)?1:((j<b.j)?-1:0),
> (k>b.k)?1:((k<b.k)?-1:0));
> }
> 
> 
> The solution would be to have a method such as:
> 
> vector opGreater (vector b) {
> return vector(i>b.i, j>b.j, k>b.k);
> }
> 
> But D should still support opCmp because it is correct in most cases.
> 
> So to support both, the compiler should parse (a>b) and call
> a.opGreater(b). The Object.opGreater method would then return
> (a.opCmp(b)==1).
> 
> Then, if the class overloads opGreater, the compiler will use that one instead and ignore opCmp for that class.

May 07, 2004
Patrick Horn wrote:

>But D should still support opCmp because it is correct in most cases.
>  
>
If its so rare then your should be satisfied with using a method instead.

-- 
-Anderson: http://badmama.com.au/~anderson/
May 07, 2004
Patrick Horn wrote:

> Currently in D there is a opCmp function returning a -1 if less, 0 if equal or 1
> if greater.  But this does not apply to classes where there the less or greater
> doesn't strictly return True or False.
<snip>

opCmp (and hence < > <= >=) is designed to be a total ordering for such purposes as sorting and binary searching.  Having it representing a partial ordering would open up a whole new can of worms.

Some would argue that it would be handy to be able to invent your own operators, but it raises such questions as precedence, associativity and naming the implementation method.

Maybe a set of generic partial ordering operations could be invented, with opPartCmp like opCmp but returning some magic value (perhaps int.min) to denote neither greater, less nor equivalent.

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.
May 07, 2004
On Fri, 7 May 2004 17:58:10 +1000, Derek Parnell wrote:

> On Fri, 7 May 2004 06:52:53 +0000 (UTC), Patrick Horn wrote:
> 
>> Currently in D there is a opCmp function returning a -1 if less, 0 if equal or 1 if greater.  But this does not apply to classes where there the less or greater doesn't strictly return True or False.

[SNIP]
> 
> You might have to resort to this sort of thing...
> 
>   // WARNING; code not tested, just indicative code only.
>   Vector a,b,c
>   Vector gtVector = new Vector(1,1,1)
>   Vector ltVector = new Vector(-1,-1,-1)
>   Vector eqVector = new Vector(0,0,0)
>   . . .
>   c = (a > b);
>   switch (c)
>   {
>    case gtVector:
>     // do Greater-Than processing
>      break;
>    case ltVector:
>     // do LessThan processing
>     break;
>    case eqVector:
>     // do Equality processing
>     break;
>    default:
>     // do mixed processing
>     break;
>   };

This is what I get when thinking while trying real hard to leave the office on time! This is a *very-silly-idea*. Sorry people.

It would be easier to live with opCmp() and create your own opGreater() etc functions for the vector class. Yes, that means you won't get " a < b " calling it, but at least your code will work as you expect it to.

There are certain commly used vectors that opCmp() works perfectly for -
strings!

-- 
Derek
Melbourne, Australia
May 07, 2004
Derek wrote:

>On Fri, 7 May 2004 17:58:10 +1000, Derek Parnell wrote:
>  
>
>
>
>This is what I get when thinking while trying real hard to leave the office
>on time! This is a *very-silly-idea*. Sorry people.
>
>It would be easier to live with opCmp() and create your own opGreater() etc
>functions for the vector class. Yes, that means you won't get " a < b "
>calling it, but at least your code will work as you expect it to.
>
>There are certain commly used vectors that opCmp() works perfectly for -
>strings!
>
>  
>
Exactly!  I see opCmp for anything (including vectors) as a sorting tool more then anything else.  I find it very useful to be able to sort 3d vectors.

You wouldn't be able to sort these objects, if there was an opGreater like Patrick requests.

-- 
-Anderson: http://badmama.com.au/~anderson/
May 10, 2004
Patrick Horn schrieb:

> In this class, for two vectors a and b, comparing a < b does not work because
> vectors can be both greater and less (a.i<b.i but a.j>b.j)
> But the problem is that opCmp can only return 1, -1 or 0, but nothing in
> between. opCmp *must* return an int to work, because the compiler must return a
> boolean to the expression (a>b). Therefore, this function would be invalid:

Harrr. Where have you studied math? To compare vectors (just as any multi-dimensional value), you need a norm. I suggest you google after Euclidian norm for vectors. Another valid norm would be e.g. a sum over all vector components, because it is a special case of a norm("[...]") |[A+B]| <= |[A] + [B]| definition.

This gets you back to linear values. Comparing anything else using operators is counter-intuitive for the program reader/user (however intuitive it may be for a programmer), and it is one of the goals of D programming language to create a quality standard for software engineering. Which includes: No operator misuse. It is a wise decision made by Walter as he laid the groundwork of D.

-eye