www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why is mostNegative!T not of type T?

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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
next sibling parent reply SealabJaster <sealabjaster gmail.com> writes:
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
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/17/21 4:00 PM, SealabJaster wrote:
 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`
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.
Oct 17 2021
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
 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
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 10/17/21 4:32 PM, Steven Schveighoffer wrote:
 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-b7918b17cede734a2dd4ecbf2a981d597a5978f52e02f9a3c6f53 9abd797f05R961-R966 ;)
Before looking: I bet it was me. After looking: woe is me.
Oct 17 2021
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
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. :) Ali
Oct 17 2021
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
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. :)
 
 Ali
Well put. I had some quite naïve ideas back then.
Oct 17 2021