Thread overview
Why does std.container.array does not work with foraech( i, a; array ) {} ?
May 29, 2016
ParticlePeter
May 29, 2016
Jonathan M Davis
May 29, 2016
Mithun Hunsur
May 29, 2016
ParticlePeter
May 29, 2016
Which of the op(Index) operators is responsible for enabling this kind of syntax?
Would it be possible to get it work with UFCS or would I have to wrap the array?

May 29, 2016
On Sunday, May 29, 2016 07:14:12 ParticlePeter via Digitalmars-d-learn wrote:
> Which of the op(Index) operators is responsible for enabling this
> kind of syntax?
> Would it be possible to get it work with UFCS or would I have to
> wrap the array?

std.container.array.Array works with foreach via ranges.

foreach(e; myContainer)
{
}

gets lowered to

foreach(e; myContainer[])
{
}

which in turn gets lowered to something like

for(auto r = myContainer[]; !r.empty; r.popFront())
{
    auto e = r.front;
}

Ranges do not support indices with foreach, and that's why you're not able to get the index with foreach and Array. However, if you use std.range.lockstep, you can wrap a range to get indices with foreach. e.g.

foreach(i, e; lockstep(myContainer[]))
{
}

http://dlang.org/phobos/std_range.html#.lockstep

- Jonathan M Davis

May 29, 2016
On Sunday, 29 May 2016 at 09:07:07 UTC, Jonathan M Davis wrote:
> On Sunday, May 29, 2016 07:14:12 ParticlePeter via Digitalmars-d-learn wrote:
>> [...]
>
> std.container.array.Array works with foreach via ranges.
>
> foreach(e; myContainer)
> {
> }
>
> gets lowered to
>
> foreach(e; myContainer[])
> {
> }
>
> which in turn gets lowered to something like
>
> for(auto r = myContainer[]; !r.empty; r.popFront())
> {
>     auto e = r.front;
> }
>
> Ranges do not support indices with foreach, and that's why you're not able to get the index with foreach and Array. However, if you use std.range.lockstep, you can wrap a range to get indices with foreach. e.g.
>
> foreach(i, e; lockstep(myContainer[]))
> {
> }
>
> http://dlang.org/phobos/std_range.html#.lockstep
>
> - Jonathan M Davis

I'd say that std.range.enumerate is more indicative of intent:

http://dlang.org/phobos/std_range.html#enumerate
May 29, 2016
On Sunday, 29 May 2016 at 09:07:07 UTC, Jonathan M Davis wrote:
> On Sunday, May 29, 2016 07:14:12 ParticlePeter via Digitalmars-d-learn wrote:
>> Which of the op(Index) operators is responsible for enabling this
>> kind of syntax?
>> Would it be possible to get it work with UFCS or would I have to
>> wrap the array?
>
> std.container.array.Array works with foreach via ranges.
>
> foreach(e; myContainer)
> {
> }
>
> gets lowered to
>
> foreach(e; myContainer[])
> {
> }
>
> which in turn gets lowered to something like
>
> for(auto r = myContainer[]; !r.empty; r.popFront())
> {
>     auto e = r.front;
> }
>
> Ranges do not support indices with foreach, and that's why you're not able to get the index with foreach and Array. However, if you use std.range.lockstep, you can wrap a range to get indices with foreach. e.g.
>
> foreach(i, e; lockstep(myContainer[]))
> {
> }
>
> http://dlang.org/phobos/std_range.html#.lockstep
>
> - Jonathan M Davis


Thanks, due to your answer I found a way which is even better for me. I pimped the Array containers with some UFCS functions anyway, one of them returns the array data as a slice and this works nicely with that foreach variant as well

auto data( T )( Array!T array )  {
    if( array.length == 0 ) return null;
    return (&array.front())[ 0..array.length ];
}

// this works now
foreach( i, a; someArrayContainer.data ) { ... }

- PP