how to correctly populate an array of dynamic closures?

Ivan Kazmenko gassa at mail.ru
Thu Mar 29 18:21:53 UTC 2018


On Thursday, 29 March 2018 at 15:38:14 UTC, ag0aep6g wrote:
> <...> With immutable, this is certainly a problem. 
> https://issues.dlang.org/show_bug.cgi?id=2043

Wow, such history for the bug!

> Two possible workarounds:
>
>     int delegate () [] iuns;
>     foreach (i; 0..2) iuns ~= (j) { return () => j; } (i);
>     foreach (i; 0..2) writeln (iuns[i] ());  /* 0 and 1 */
>
>     static struct S
>     {
>         int i;
>         int m() { return i; }
>     }
>     int delegate () [] juns;
>     foreach (i; 0..2) juns ~= &(new S(i)).m;
>     foreach (i; 0..2) writeln (juns[i] ());  /* 0 and 1 */

Thank you ag0aep6g and Dennis for showing the possible 
workarounds!

On Thursday, 29 March 2018 at 15:47:33 UTC, Dennis wrote:
> A delegate is a function with a pointer to the stack frame 
> where it was created. It doesn't copy or insert the value of 
> 'i', it still refers to the very same location in memory as the 
> i from the for-loop. After the for-loop, that value is 1, so 
> all delegates refering to that i return 1. The solution is to 
> generate a new local variable for each closure with a helper 
> function:

So, basically, one has to create and call another function, or 
explicitly copy onto the heap, in order to ensure the copy of the 
loop variable is stored for the closure.
My (mis)understanding was that there's some additional magic 
happening for closures that get stored on the heap, as opposed to 
delegates used before their context goes out of scope.
As long as the whole story is that simple, fine.

Ivan Kazmenko.



More information about the Digitalmars-d-learn mailing list