Closures and loop scope
Timon Gehr
timon.gehr at gmx.ch
Tue Jun 4 13:52:27 PDT 2013
On 06/04/2013 09:19 PM, Idan Arye wrote:
> 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`.
>
> ...
It is not that obvious. They refer to different i's that happen to
reside at the same place in the stack frame. It's a bug.
It is more obvious that it is a bug given this code snippet:
import std.stdio, std.algorithm;
void main(){
auto arr=new ulong delegate()[5];
foreach(immutable i;0..arr.length){
arr[i]={auto j=i;return {assert(j==i); return i;};}();
}
writeln(arr.map!`a()`());
}
As you can see, 'i' mutates even though it is declared immutable.
>...
Yes. Yes.
http://d.puremagic.com/issues/show_bug.cgi?id=2043
More information about the Digitalmars-d
mailing list