www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - opLess and opGreater

reply Patrick Horn <phrh yahoo.com> writes:
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 06 2004
next sibling parent reply Derek Parnell <derek psych.ward> writes:
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
parent reply Derek <ddparnell bigpond.com> writes:
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
parent J Anderson <REMOVEanderson badmama.com.au> writes:
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!

  

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 07 2004
prev sibling next sibling parent Norbert Nemec <Norbert.Nemec gmx.de> writes:
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
prev sibling next sibling parent J Anderson <REMOVEanderson badmama.com.au> writes:
Patrick Horn wrote:

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

-- -Anderson: http://badmama.com.au/~anderson/
May 07 2004
prev sibling next sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
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.

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
prev sibling parent Ilya Minkov <minkov cs.tum.edu> writes:
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
May 10 2004