www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Comparison operator overloading

reply =?UTF-8?B?TcOhcmNpbw==?= Martins <marcioapm gmail.com> writes:
I am writing a generic numerical array struct, and I can't find a 
way to do element-wise comparison operators.

What I had envisioned was something like the following, assuming 
a, b, c and m are array-like, and all operations return arrays.

auto m = (a > b) * a + 15;
auto c = a.choose(a > b)^^2;

However, it seems this can't be achieved at the moment, as far as 
I can tell.

The rewriting of a >= b to a.opCmp(b) >= 0 seems limiting in the 
sense that it assumes scalar-like operands and semantics, which 
is surprising, and goes against the awesome flexibility of the 
remaining operator overloads.

Tried to look around, but according to google, the only reference 
I have seen to this was someone with a similar question in 2004, 
which is surprising to say the least. I suppose either I am 
missing something really obvious, or I am out of luck?
Dec 06 2015
next sibling parent reply cym13 <cpicard openmailbox.org> writes:
On Sunday, 6 December 2015 at 14:41:01 UTC, Márcio Martins wrote:
 I am writing a generic numerical array struct, and I can't find 
 a way to do element-wise comparison operators.

 What I had envisioned was something like the following, 
 assuming a, b, c and m are array-like, and all operations 
 return arrays.

 auto m = (a > b) * a + 15;
 auto c = a.choose(a > b)^^2;

 However, it seems this can't be achieved at the moment, as far 
 as I can tell.

 The rewriting of a >= b to a.opCmp(b) >= 0 seems limiting in 
 the sense that it assumes scalar-like operands and semantics, 
 which is surprising, and goes against the awesome flexibility 
 of the remaining operator overloads.

 Tried to look around, but according to google, the only 
 reference I have seen to this was someone with a similar 
 question in 2004, which is surprising to say the least. I 
 suppose either I am missing something really obvious, or I am 
 out of luck?
Don't use opCmp, all binary operators should be overriden using opBinary. For more information I recommend this page http://ddili.org/ders/d.en/operator_overloading.html
Dec 06 2015
parent reply Dominikus Dittes Scherkl <Dominikus.Scherkl continental-corporation.com> writes:
On Sunday, 6 December 2015 at 15:01:08 UTC, cym13 wrote:
 Don't use opCmp, all binary operators should be overriden using 
 opBinary. For more information I recommend this page 
 http://ddili.org/ders/d.en/operator_overloading.html
Why should we don't use opCmp() ? I can't see any recommendation about this in the cited book. In the chapter is only mentioned that opSliceAssign() and the like are discouraged - but without stating a reason or a replacement. On the other hand the chapter also states that opCmp() should always return "int" - which is a bad idea if you e.g. want to provide a "NaN" value in your type. For that "float" is a much better return type for opCmp(). So you should not weight in gold for the words in the cited book, I think.
Dec 07 2015
parent reply Mike Parker <aldacron gmail.com> writes:
On Monday, 7 December 2015 at 11:49:51 UTC, Dominikus Dittes 
Scherkl wrote:
 On Sunday, 6 December 2015 at 15:01:08 UTC, cym13 wrote:
 Don't use opCmp, all binary operators should be overriden 
 using opBinary. For more information I recommend this page 
 http://ddili.org/ders/d.en/operator_overloading.html
Why should we don't use opCmp() ? I can't see any recommendation about this in the cited book. In
That chapter actually shows quite clearly in the table in the Binary Operators section that opCmp is used for <, <=, >, and >=, which is also exactly what the language reference says. There's also another section further down the page that covers opCmp explicitly. I have no idea what cym13 is looking at.
 On the other hand the chapter also states that opCmp() should 
 always return "int" - which is a bad idea if you e.g. want to 
 provide a "NaN" value in your type. For that "float" is a much 
 better return type for opCmp().
 So you should not weight in gold for the words in the cited 
 book, I think.
This is not something the author is just making up. opCmp is expected to return int because of the way the compiler rewrites comparison expressions. See the table at [1]. It wouldn't do to return NaN from opCmp. [1] http://dlang.org/spec/operatoroverloading.html#compare
Dec 07 2015
parent reply Dominikus Dittes Scherkl <Dominikus.Scherkl continental-corporation.com> writes:
On Monday, 7 December 2015 at 13:31:52 UTC, Mike Parker wrote:
 On Monday, 7 December 2015 at 11:49:51 UTC, Dominikus Dittes 
 Scherkl wrote:
 On the other hand the chapter also states that opCmp() should 
 always return "int" - which is a bad idea if you e.g. want to 
 provide a "NaN" value in your type. For that "float" is a much 
 better return type for opCmp().
 So you should not weight in gold for the words in the cited 
 book, I think.
This is not something the author is just making up. opCmp is expected to return int because of the way the compiler rewrites comparison expressions. See the table at [1]. It wouldn't do to return NaN from opCmp. [1] http://dlang.org/spec/operatoroverloading.html#compare
Hmm. But it works just fine! It overloads also the special floatingpoint operators <> !<> !<= and so on. And how else could I handle a self-defined type that happens to have a NaN value (like my save-signed intergers do)?
Dec 07 2015
parent Anonymous <anon anon.anon> writes:
On Monday, 7 December 2015 at 17:18:20 UTC, Dominikus Dittes 
Scherkl wrote:
 Hmm. But it works just fine! It overloads also the special 
 floatingpoint operators <> !<> !<= and so on.
Those are deprecated: http://dlang.org/deprecate.html#Floating%20point%20NCEG%20operators
 And how else could I handle a self-defined type that happens to 
 have a NaN value (like my save-signed intergers do)?
Something like this: http://dlang.org/phobos/std_math.html#isNaN Or maybe this: http://dlang.org/phobos/std_typecons.html#Nullable Obviously, you'd want to do what makes sense for your type and its semantics. That probably doesn't involve using NCEG operators.
Dec 07 2015
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 12/06/2015 06:41 AM, Márcio Martins wrote:

 auto m = (a > b) * a + 15;
 auto c = a.choose(a > b)^^2;
What do those operations do? Are you thinking of a special meaning for '>', perhaps common in numerical computations, which I'm not familiar with? If I understand correctly, 'a > b' in choose(a > b) is the condition to pick elements from a. If so, it is better to pass a lambda in such cases: a.choose!((i, j) => i > j); However, as I understand it, the whole expression is supposed to generate an array-like result. Is that right? :) Ali
Dec 06 2015
parent =?UTF-8?B?TcOhcmNpbw==?= Martins <marcioapm gmail.com> writes:
On Monday, 7 December 2015 at 00:43:50 UTC, Ali Çehreli wrote:
 On 12/06/2015 06:41 AM, Márcio Martins wrote:

 auto m = (a > b) * a + 15;
 auto c = a.choose(a > b)^^2;
What do those operations do? Are you thinking of a special meaning for '>', perhaps common in numerical computations, which I'm not familiar with? If I understand correctly, 'a > b' in choose(a > b) is the condition to pick elements from a. If so, it is better to pass a lambda in such cases: a.choose!((i, j) => i > j); However, as I understand it, the whole expression is supposed to generate an array-like result. Is that right? :) Ali
Yes, each expression involving these arrays will almost always also result in another array, sometimes with a different type. For example, a > b returns an array of bools whose elements are the the result of the condition applied to each individual element of a and b. This makes writing numerical code very easy, and with fewer bugs, because it's all very succinct and each operation is very simple and well defined. My initial intuition was that opBinary and opBinaryRight would be used if suitable and opCmp/opEquals would be the fallback. That didn't seem to work, so I quickly realised this is not possible in D. I'm wondering if it is an oversight in the language design or there are real reasons for this limitation?
Dec 07 2015