[OT] The Usual Arithmetic Confusions

Timon Gehr timon.gehr at gmx.ch
Fri Feb 18 00:33:45 UTC 2022


On 17.02.22 18:53, bachmeier wrote:
> On Friday, 28 January 2022 at 02:15:51 UTC, Paul Backus wrote:
>> Unfortunately, this is also one of the areas of D that comes directly 
>> from C, so D programmers have to watch out for these as well.
> 
> Here's a lovely one I wrote about yesterday in Learn:
> 
> ```
> import std.conv, std.range, std.stdio;
> 
> void main() {
>      writeln(iota(5, 0, -1));
>      writeln(iota(5, -1, -1));
>      writeln(iota(5.to!uint, -1, -1));
>      writeln(iota(5.to!uint, 0, -1));
>      writeln(-1.to!uint);
>      auto z = -1;
>      writeln(z.to!uint);
> }
> ```
> 
> Which delivers the following output:
> 
> ```
> [5, 4, 3, 2, 1]
> [5, 4, 3, 2, 1, 0]
> []
> [5, 4, 3, 2, 1]
> 4294967295
> std.conv.ConvOverflowException@/usr/include/dmd/phobos/std/conv.d(567): 
> Conversion negative overflow
> ----------------
> ??:? pure @safe bool std.exception.enforce!(bool).enforce(bool, lazy 
> object.Throwable) [0x555fe1c5c946]
> ??:? pure @safe uint std.conv.toImpl!(uint, int).toImpl(int) 
> [0x555fe1c6f1ff]
> ??:? pure @safe uint std.conv.to!(uint).to!(int).to(int) [0x555fe1c6f1d0]
> ??:? _Dmain [0x555fe1c5594c]
> ```
> 
> All I wanted was a function that iterates through the elements of an 
> array starting at the end. The only time you have a problem is if you 
> want to include the first element of the array.
> 
> A simple solution is to add a `-scottmeyers` switch that retains full 
> compatibility with C, but sets the default as a language that is 
> productive.


Not defending C rules at all or how Phobos is handling them, but if you 
want a range with all array indices in reverse, there is a very simple 
way to state just that:

```d
import std.conv, std.range, std.stdio;

void main() {
     auto v = [1, 2, 3, 4, 5];
     writeln(iota(v.length).retro);
}
```

In general, I avoid using negation/subtraction if anything unsigned is 
involved. There is usually another way to write it, in this case it is 
even much simpler, more descriptive, and it will work correctly for long 
arrays. (`int`/`uint` are not large enough to address modern amounts of 
RAM. However, I guess instead of avoiding negation/subtraction, it can 
also make sense to do index computations with `long` instead of `size_t`.)


More information about the Digitalmars-d mailing list