Closures and loop scope
Idan Arye
GenericNPC at gmail.com
Tue Jun 4 12:19:56 PDT 2013
Consider the following code. What will it print?
auto arr=new ulong delegate()[5];
foreach(i;0..arr.length){
arr[i]=()=>i;
}
writeln(arr.map!`a()`());
It is natural to expect that it will print [0, 1, 2, 3, 4], but
it actually prints [5, 5, 5, 5, 5]. The reason is obvious - all
the delegates refer to the same `i` in their closures, and at the
end of the loop that `i` is set to `5`.
While this makes some sense when you consider how the closures
are implemented, it is still not what you expect from that code.
`i` is supposed to be local to each iteration of the loop, and
here it "leaks" between the iterations.
There is an hackaround:
auto arr=new ulong delegate()[5];
foreach(i;0..arr.length){
arr[i]=(j=>()=>j)(i);
}
writeln(arr.map!`a()`());
This prints [0, 1, 2, 3, 4] as expected, since we use another
function to create a separate stack frame to store the value of
`i`. A different way to implement that idea:
auto arr=new ulong delegate()[5];
foreach(i;0..arr.length){
arr[i]={
auto j=i;
return ()=>j;
}();
}
writeln(arr.map!`a()`());
Can this be fixed? *Should* this be fixed?
Discuss
More information about the Digitalmars-d
mailing list