Unexpected behaviour of foreach statement

Jonathan M Davis newsgroup.d at jmdavisprog.com
Fri Mar 2 10:32:08 UTC 2018


On Friday, March 02, 2018 10:21:39 Arredondo via Digitalmars-d-learn wrote:
> Hi,
>
> The following works as expected:
>
> auto range = [1, 2, 3, 4, 5];
> foreach (i, el; range) {
>   writeln(i, ": ", el);
> }
>
> but this slight modification doesn't:
>
> auto range = iota(5);
> foreach (i, el; range) {
>   writeln(i, ": ", el);
> }
>
> DMD 2.078.3 says:
> Error: cannot infer argument types, expected 1 argument, not 2
>
> The error message is not helpful either, because indicating the
> types, as in:
>
> foreach (int i, int el; range) { ... }
>
> throws the same error.
> What's going on here?

foreach does not support indices for ranges, only arrays. When you have

foreach(e; range)

it gets lowered to

foreach(auto __range = range; !__range.empty; __range.popFront())
{
    auto e = __range.front;
}

There are no indices involved there, and if a range isn't a random-access
range, it doesn't support any kind of indices anyway. The compiler would
have to add a variable to count the elements, and it doesn't support that.

Your best options are either lockstep with iota or enumerate:

https://dlang.org/phobos/std_range.html#lockstep
https://dlang.org/phobos/std_range.html#enumerate

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list