Can opCmp return a 'long' instead of 'int'?

2014-02-16 Thread Saurabh Das

Hello,

The call signature for opCmp in a struct is:

struct S {
  int opCmp(ref const S s) const { ... }
}

int opCmp(ref const S s) const { return _val - s._val; }

This works fine if _val is 'int'. However, if _val is 'long' then 
subtracting 2 longs may not result in an int - and therefore I 
would have to replace the subtraction above with 2 comparison 
operators.


My question is: Can I rewrite opCmp to return a 'long', like:

struct S {
  long opCmp(ref const S s) const { return _val - s.val; }
}

This does compile and run correctly, but are there any hidden 
assumptions or requirements on the return value of opCmp that I 
should be aware of? Is there any reason that doing this may be 
not be wise?


Thanks,
Saurabh


Re: Can opCmp return a 'long' instead of 'int'?

2014-02-16 Thread Timon Gehr

On 02/16/2014 02:59 PM, Saurabh Das wrote:


This does compile and run correctly, but are there any hidden
assumptions or requirements on the return value of opCmp that I should
be aware of? Is there any reason that doing this may be not be wise?


No, this is fine.


Re: Can opCmp return a 'long' instead of 'int'?

2014-02-16 Thread Timon Gehr

On 02/16/2014 04:13 PM, Timon Gehr wrote:

On 02/16/2014 02:59 PM, Saurabh Das wrote:


This does compile and run correctly, but are there any hidden
assumptions or requirements on the return value of opCmp that I should
be aware of? Is there any reason that doing this may be not be wise?


No, this is fine.


To be more precise: Returning long is fine.

The subtraction trick does not work in general regardless of return type:

import std.stdio;
struct S{
int d;
int opCmp(S r){ return d - r.d; }
}

void main(){
assert(S(1)S(2)); // passes. ok.
assert(S(int.min)S(int.max)); // passes. oops.
}



Re: Can opCmp return a 'long' instead of 'int'?

2014-02-16 Thread bearophile

Timon Gehr:


assert(S(1)S(2)); // passes. ok.
assert(S(int.min)S(int.max)); // passes. oops.


A possible solution is to add to Phobos (unless it's already 
there) a variadic templated funcion cmpBuilder() that accepts an 
even number of arguments, that are seen as pairs. Usage example:


struct Foo {
  int x, y;
  string s;
  int opCmp(in ref Foo r) {
return cmpBuilder(x, r.x, y.abs, r.y.abs, s, r.s);
  }
}

Is this worth adding to Phobos?

Bye,
bearophile


Re: Can opCmp return a 'long' instead of 'int'?

2014-02-16 Thread Timon Gehr

On 02/16/2014 04:40 PM, bearophile wrote:

Timon Gehr:


assert(S(1)S(2)); // passes. ok.
assert(S(int.min)S(int.max)); // passes. oops.


A possible solution is to add to Phobos (unless it's already there) a
variadic templated funcion cmpBuilder() that accepts an even number of
arguments, that are seen as pairs. Usage example:

struct Foo {
   int x, y;
   string s;
   int opCmp(in ref Foo r) {
 return cmpBuilder(x, r.x, y.abs, r.y.abs, s, r.s);
   }
}

Is this worth adding to Phobos?

Bye,
bearophile


IMO no (lots of repetition), but forwarding opCmp is:

struct Foo{
int x,y;
string s;
private @property order(){ return tuple(x, abs(y), s); }
mixin OrderBy!order;
}

Furthermore, the language should be updated such that the built-in types 
are not special w.r.t. operators. Eg:


1.opBinary!+(2)
1.opCmp(2)

should work.

The following should be supported as well:

struct Foo{
int x,y;
string s;
mixin OrderBy!(()=tuple(x, abs(y), s));
}

(Currently DMD bans function literals as members.)


Re: Can opCmp return a 'long' instead of 'int'?

2014-02-16 Thread Saurabh Das

On Sunday, 16 February 2014 at 15:19:08 UTC, Timon Gehr wrote:

On 02/16/2014 04:13 PM, Timon Gehr wrote:

On 02/16/2014 02:59 PM, Saurabh Das wrote:


This does compile and run correctly, but are there any hidden
assumptions or requirements on the return value of opCmp that 
I should
be aware of? Is there any reason that doing this may be not 
be wise?


No, this is fine.


To be more precise: Returning long is fine.

The subtraction trick does not work in general regardless of 
return type:


import std.stdio;
struct S{
int d;
int opCmp(S r){ return d - r.d; }
}

void main(){
assert(S(1)S(2)); // passes. ok.
assert(S(int.min)S(int.max)); // passes. oops.
}


Right. I didn't expect that! So I shouldn't use it anyway. Thanks!

Saurabh