digitalmars.D - opCmp with template type not working.
- Jonathan Levi (7/20) Nov 02 2020 With:
- rikki cattermole (4/4) Nov 02 2020 Two questions:
- user1234 (4/24) Nov 02 2020 opCmp should return a signed integer. This allows to match well
- Jonathan Levi (4/7) Nov 02 2020 Um, I missed that. Man, I have some old errors in my code. I
- ag0aep6g (4/7) Nov 02 2020 Doing comparison by subtracting is a cute idea, but it doesn't actually
- Andrei Alexandrescu (3/12) Nov 03 2020 druntime does it for integrals smaller than int. For others, you can do:
- Andrei Alexandrescu (3/17) Nov 03 2020 Ehm.
- Dominikus Dittes Scherkl (9/10) Nov 04 2020 No. opCmp should return a float, to have all 4 possible
- Paul Backus (8/18) Nov 04 2020 opCmp can return whatever you want, as long as it is comparable
- Dominikus Dittes Scherkl (13/17) Nov 08 2020 Yeah, but int is 32 bit, same as float. So why use a type that
- Paul Backus (11/18) Nov 08 2020 For types that are totally ordered, it's easier for the user if
This is not working as expected:bool opCmp(string op, U)(U rhs) {As it does work with:auto opBinary(string op, U)(U rhs) {With:struct X { int x; auto opBinary(string op, U)(U rhs) { return mixin("x "~op~" rhs"); } bool opCmp(string op, U)(U rhs) { return mixin("x "~op~" rhs"); } }This compiles:X(5) + 4This does not:X(5) < 4Full example code: https://run.dlang.io/is/Beflkt Is this a Bug?
Nov 02 2020
Two questions: 1) Why is opCmp returning a bool? 2) Why does opCmp have a template parameter called `op`? https://dlang.org/spec/operatoroverloading.html#compare
Nov 02 2020
On Tuesday, 3 November 2020 at 02:55:46 UTC, Jonathan Levi wrote:This is not working as expected:opCmp should return a signed integer. This allows to match well with the x86 flag register and do fast comparison with integers types (in which case just substract rhs to lhs and you're good)bool opCmp(string op, U)(U rhs) {As it does work with:auto opBinary(string op, U)(U rhs) {With:struct X { int x; auto opBinary(string op, U)(U rhs) { return mixin("x "~op~" rhs"); } bool opCmp(string op, U)(U rhs) { return mixin("x "~op~" rhs"); } }This compiles:X(5) + 4This does not:X(5) < 4Full example code: https://run.dlang.io/is/Beflkt Is this a Bug?
Nov 02 2020
On Tuesday, 3 November 2020 at 03:07:14 UTC, user1234 wrote:opCmp should return a signed integer. This allows to match well with the x86 flag register and do fast comparison with integers types (in which case just substract rhs to lhs and you're good)Um, I missed that. Man, I have some old errors in my code. I had opCmp implemented that way for a while, and apparently never tested or used it. I see that now in the spec.
Nov 02 2020
On 03.11.20 04:07, user1234 wrote:opCmp should return a signed integer. This allows to match well with the x86 flag register and do fast comparison with integers types (in which case just substract rhs to lhs and you're good)Doing comparison by subtracting is a cute idea, but it doesn't actually work in general because of wraparound. Example: int.min < 1, but int.min - 1 > 0.
Nov 02 2020
On 11/3/20 1:56 AM, ag0aep6g wrote:On 03.11.20 04:07, user1234 wrote:druntime does it for integrals smaller than int. For others, you can do: return (a > b) - (b < a);opCmp should return a signed integer. This allows to match well with the x86 flag register and do fast comparison with integers types (in which case just substract rhs to lhs and you're good)Doing comparison by subtracting is a cute idea, but it doesn't actually work in general because of wraparound. Example: int.min < 1, but int.min - 1 > 0.
Nov 03 2020
On 11/3/20 8:48 AM, Andrei Alexandrescu wrote:On 11/3/20 1:56 AM, ag0aep6g wrote:Ehm. return (a > b) - (a < b);On 03.11.20 04:07, user1234 wrote:druntime does it for integrals smaller than int. For others, you can do: return (a > b) - (b < a);opCmp should return a signed integer. This allows to match well with the x86 flag register and do fast comparison with integers types (in which case just substract rhs to lhs and you're good)Doing comparison by subtracting is a cute idea, but it doesn't actually work in general because of wraparound. Example: int.min < 1, but int.min - 1 > 0.
Nov 03 2020
On Tuesday, 3 November 2020 at 03:07:14 UTC, user1234 wrote:opCmp should return a signed integer.No. opCmp should return a float, to have all 4 possible comparison results available: greater (1) lower (-1) equal (0) and not comparable (NaN) Especially the last one is necessary if you like to have opCmp defined on some not completely ordered set.
Nov 04 2020
On Wednesday, 4 November 2020 at 09:01:21 UTC, Dominikus Dittes Scherkl wrote:On Tuesday, 3 November 2020 at 03:07:14 UTC, user1234 wrote:opCmp can return whatever you want, as long as it is comparable with 0 using the `<`, `>`, `<=`, and `>=` operators: https://dlang.org/spec/operatoroverloading.html#compare IMO there's no reason to use a floating-point number unless you specifically need partial ordering. For the common case of a totally-ordered type, a signed integer is fine.opCmp should return a signed integer.No. opCmp should return a float, to have all 4 possible comparison results available: greater (1) lower (-1) equal (0) and not comparable (NaN) Especially the last one is necessary if you like to have opCmp defined on some not completely ordered set.
Nov 04 2020
On Wednesday, 4 November 2020 at 15:51:04 UTC, Paul Backus wrote:opCmp can return whatever you want, [...] IMO there's no reason to use a floating-point number unless you specifically need partial ordering. For the common case of a totally-ordered type, a signed integer is fine.Yeah, but int is 32 bit, same as float. So why use a type that restricts the use cases without any benefit? Simply always use float, so you have no changes if you later detect that your type to compare is in fact _not_ totally ordered (e.g. has some special cases). And beliefe me, for most types you will earlier or later detect, that they are not totally ordered. Today when I look, most libraries do some ugly and non-performant special casing because their comparison operators didn't handle the not-comparable case correctly. In D we can do better, as we CAN handle it. So everybody should be taught to use float as the result of opCmp. The earlier we do it correct, the better for the language!
Nov 08 2020
On Sunday, 8 November 2020 at 12:52:14 UTC, Dominikus Dittes Scherkl wrote:Yeah, but int is 32 bit, same as float. So why use a type that restricts the use cases without any benefit?For types that are totally ordered, it's easier for the user if they don't have to consider the possibility that opCmp will return NaN.Simply always use float, so you have no changes if you later detect that your type to compare is in fact _not_ totally ordered (e.g. has some special cases). And beliefe me, for most types you will earlier or later detect, that they are not totally ordered.I'm skeptical of the idea that "most" types are partially ordered, but even if they are, so what? The only code that will break if you change the return type of opCmp from int to float after the fact is code that's calling `.opCmp` directly--and you probably *want* that code to break if you're switching from a total order to a partial one.
Nov 08 2020