Bring back foreach int indexes

Quirin Schroll qs.il.paperinik at gmail.com
Mon Dec 11 22:22:27 UTC 2023


On Wednesday, 29 November 2023 at 15:48:25 UTC, Steven 
Schveighoffer wrote:
> On Wednesday, 29 November 2023 at 14:56:50 UTC, Steven 
> Schveighoffer wrote:
>> I don’t know how many times I get caught with size_t indexes 
>> but I want them to be int or uint. It’s especially painful in 
>> my class that I’m teaching where I don’t want to yet explain 
>> why int doesn’t work there and have to introduce casting or 
>> use to!int. All for the possibility that I have an array 
>> larger than 2 billion elements.
>>
>> I am forgetting why we removed this in the first place.
>>
>> Can we have the compiler insert an assert at the loop start 
>> that the bounds are in range when you use a smaller int type? 
>> Clearly the common case is that the array is small enough for 
>> int indexes.
>
>
> For those who are unaware, this used to work:
>
> ```d
> auto arr = [1, 2, 3];
> foreach(int idx, v; arr) {
>     ...
> }
> ```
>
> But was removed at some point. I think it should be brought 
> back (we are bringing stuff back now, right? Like hex strings?)
>
> -Steve

Couldn’t you write a function `withIntIndex` or 
`withIndexType!int` such that you can check the array is indeed 
short enough?

```d
auto withIndexType(T : ulong, U)(U[] array)
{
     static struct WithIndexType
     {
         U[] array;
         int opApplyImpl(DG)(scope DG callback)
         {
             for (T index = 0; index < cast(T)array.length; 
++index)
             {
                 if (auto result = callback(index, array[index])) 
return result;
             }
             return 0;
         }
         alias opApply = opApplyImpl!(int delegate(T, ref U));
     }
     assert(array.length < T.max, "withIndexType: array length is 
too big for index type");
     return WithIndexType(array);
}
```

The `alias opApply` makes it so that this works (notice `@safe` 
on `main`):
```d
void main() @safe
{
     double[] xs = new double[](120);
     foreach (i, ref d; xs.withIndexType!byte)
     {
         static assert(is(typeof(i) == byte));
         static assert(is(typeof(d) == double));
         // your part :)
     }
}
```

In all honesty, I don’t know why the `alias` trick even works, 
but using it, the compiler can infer the `foreach` types _and_ 
instantiate the `opApplyImpl` template with the concrete type of 
the loop delegate.


More information about the Digitalmars-d mailing list