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