Delegate, scope and associative array
Rene Zwanenburg via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Mon Jun 2 16:43:58 PDT 2014
On Monday, 2 June 2014 at 20:09:12 UTC, Edwin van Leeuwen wrote:
> I'm probably missing something basic, but I am confused by what
> is going on in the following code.
>
> unittest {
> size_t delegate()[size_t] events;
> foreach( i; 1..4 ) {
> events[i] = { return i; };
> }
> writeln( events[1]() ); // This outputs 3
> assert( events[1]() == 1 );
> }
>
> I thought that i should be copied from the local scope and
> therefore when I call events[1]() the return value should be 1,
> but in this case it is 3 (it always seems to be the last value
> of i in the loop).
>
> Cheers, Edwin
Yeah this is a known problem. At the moment the foreach loop is
internally rewritten to something like
int i = 1;
while(i < 4)
{
// foreach loop body
++i;
}
While it usually would be preferrable if it were rewritten as
int __compilergeneratedname = 1;
while(__compilergeneratedname < 4)
{
auto i = __compilergeneratedname++;
// foreach loop body
}
With the current approach every delegate refers to the same
variable. Another problem is that it's possible to alter the
iteration index from inside the foreach body.
As you may have guessed, a workaround is to copy the iteration
variable yourself:
unittest {
size_t delegate()[size_t] events;
foreach(_i; 1..4 ) {
auto i = _i;
events[i] = { return i; };
}
assert( events[1]() == 1 );
}
This should work though it's less than ideal. There is an open
bug report:
https://issues.dlang.org/show_bug.cgi?id=8621
More information about the Digitalmars-d-learn
mailing list