digitalmars.D - Why is mostNegative!T not of type T?
- Andrei Alexandrescu (46/46) Oct 17 2021 https://github.com/dlang/phobos/blob/master/std/traits.d#L8217
- SealabJaster (6/7) Oct 17 2021 I don't really have anything to add other than "wat".
- Andrei Alexandrescu (5/14) Oct 17 2021 That's my handiwork. Autodecoding and the trainwreck that followed.
- Andrei Alexandrescu (3/31) Oct 17 2021 Update:
- Steven Schveighoffer (5/21) Oct 17 2021 You need to ask this guy why he did it:
- Andrei Alexandrescu (3/26) Oct 17 2021 Before looking: I bet it was me.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (4/8) Oct 17 2021 Not the same guy after 13 years. :)
- Andrei Alexandrescu (2/17) Oct 17 2021 Well put. I had some quite naïve ideas back then.
https://github.com/dlang/phobos/blob/master/std/traits.d#L8217 template mostNegative(T) if (isNumeric!T || isSomeChar!T || isBoolean!T) { static if (is(typeof(T.min_normal))) enum mostNegative = -T.max; else static if (T.min == 0) enum byte mostNegative = 0; else enum mostNegative = T.min; } This is a breakage of the Rule of Least Astonishment: mostNegative!T for all unsigned types yields type byte. I tried to simplify as follows: template mostNegative(T) if (isNumeric!T || isSomeChar!T || isBoolean!T) { static if (is(typeof(T.min_normal))) enum mostNegative = -T.max; else enum mostNegative = T.min; } Got errors all the way over in unittests of std.algorithm.comparison.clamp. Looking at the definition of clamp: auto clamp(T1, T2, T3)(T1 val, T2 lower, T3 upper) if (is(typeof(max(min(val, upper), lower)))) in { import std.functional : greaterThan; assert(!lower.greaterThan(upper), "Lower can't be greater than upper."); } do { return max(min(val, upper), lower); } In turn, min and max use mostNegative and makes surprising deductions based on its type. The surprise has been deemed desirable and has become part of an unnecessarily complex mesh. The failing unittest is: int a = -5; uint f = 5; short b = 6; static assert(is(typeof(clamp(f, a, b)) == int)); This is bizarre and very arguably a bug, as one would expect clamping a value of type `whatever` would yield a value of type `whatever`.
Oct 17 2021
On Sunday, 17 October 2021 at 19:32:16 UTC, Andrei Alexandrescu wrote:...I don't really have anything to add other than "wat". I assume this was (successfully) reviewed as well before being put in, unless it's an ancient relic of past times. It gives me the same vibes as `ElementType!string == dchar`
Oct 17 2021
On 10/17/21 4:00 PM, SealabJaster wrote:On Sunday, 17 October 2021 at 19:32:16 UTC, Andrei Alexandrescu wrote:That's my handiwork. Autodecoding and the trainwreck that followed. I'm really worried that on an idle Sunday morning just reading a couple of Phobos files with an eye for refactoring uncovers a variety of oddities and bugs....I don't really have anything to add other than "wat". I assume this was (successfully) reviewed as well before being put in, unless it's an ancient relic of past times. It gives me the same vibes as `ElementType!string == dchar`
Oct 17 2021
Looking at the definition of clamp: auto clamp(T1, T2, T3)(T1 val, T2 lower, T3 upper) if (is(typeof(max(min(val, upper), lower)))) in { import std.functional : greaterThan; assert(!lower.greaterThan(upper), "Lower can't be greater than upper."); } do { return max(min(val, upper), lower); } In turn, min and max use mostNegative and makes surprising deductions based on its type. The surprise has been deemed desirable and has become part of an unnecessarily complex mesh. The failing unittest is: int a = -5; uint f = 5; short b = 6; static assert(is(typeof(clamp(f, a, b)) == int)); This is bizarre and very arguably a bug, as one would expect clamping a value of type `whatever` would yield a value of type `whatever`.Update: https://issues.dlang.org/show_bug.cgi?id=22414 https://github.com/dlang/phobos/pull/8293
Oct 17 2021
On 10/17/21 3:32 PM, Andrei Alexandrescu wrote:https://github.com/dlang/phobos/blob/master/std/traits.d#L8217 template mostNegative(T) if (isNumeric!T || isSomeChar!T || isBoolean!T) { static if (is(typeof(T.min_normal))) enum mostNegative = -T.max; else static if (T.min == 0) enum byte mostNegative = 0; else enum mostNegative = T.min; } This is a breakage of the Rule of Least Astonishment: mostNegative!T for all unsigned types yields type byte.You need to ask this guy why he did it: https://github.com/dlang/phobos/commit/399fa21dea2910b2fcd525918d5227ec536c49b4#diff-b7918b17cede734a2dd4ecbf2a981d597a5978f52e02f9a3c6f53c9abd797f05R961-R966 ;) -Steve
Oct 17 2021
On 10/17/21 4:32 PM, Steven Schveighoffer wrote:On 10/17/21 3:32 PM, Andrei Alexandrescu wrote:Before looking: I bet it was me. After looking: woe is me.https://github.com/dlang/phobos/blob/master/std/traits.d#L8217 template mostNegative(T) if (isNumeric!T || isSomeChar!T || isBoolean!T) { static if (is(typeof(T.min_normal))) enum mostNegative = -T.max; else static if (T.min == 0) enum byte mostNegative = 0; else enum mostNegative = T.min; } This is a breakage of the Rule of Least Astonishment: mostNegative!T for all unsigned types yields type byte.You need to ask this guy why he did it: https://github.com/dlang/phobos/commit/399fa21dea2910b2fcd525918d5227ec536c49b4#diff-b7918b17cede734a2dd4ecbf2a981d597a5978f52e02f9a3c6f53 9abd797f05R961-R966 ;)
Oct 17 2021
On 10/17/21 1:32 PM, Steven Schveighoffer wrote:You need to ask this guy why he did it:https://github.com/dlang/phobos/commit/399fa21dea2910b2fcd525918d5227ec536c49b4#diff-b7918b17cede734a2dd4ecbf2a981d597a5978f52e02f9a3c6f53 9abd797f05R961-R966;) -SteveNot the same guy after 13 years. :) Ali
Oct 17 2021
On 10/17/21 5:42 PM, Ali Çehreli wrote:On 10/17/21 1:32 PM, Steven Schveighoffer wrote: > You need to ask this guy why he did it: > https://github.com/dlang/phobos/commit/399fa21dea2910b2fcd525918d5227ec536c49b4#diff-b7918b17cede734a2dd4ecbf2a981d597a5978f52e02f9a3c6f53 9abd797f05R961-R966 > > > ;) > > -Steve Not the same guy after 13 years. :) AliWell put. I had some quite naïve ideas back then.
Oct 17 2021