how to correctly populate an array of dynamic closures?

Ivan Kazmenko gassa at mail.ru
Thu Mar 29 15:16:07 UTC 2018


Here's a simplified example of what I want to achieve.

I first create funs, an array of two delegates.
I want funs[0] to always return 0 and funs[1] to always return 1.

By assigning the constants directly (see the code below), I 
achieve exactly that.
Now, I want to use a loop to assign the values, and this is where 
things stop working.

My first try is guns, populated with `foreach (i; 0..2) guns ~= 
() => i;`.
But both guns[0] and guns[1] return 1.

I tried to circumvent that by populating another array, huns, 
with functions returning immutable copies of the loop variable, 
but the effect was the same.

import std.stdio;
void main () {
	int delegate () [] funs;
	funs ~= () => 0;
	funs ~= () => 1;
	foreach (i; 0..2) writeln (funs[i] ());  // 0 and 1 as expected

	int delegate () [] guns;
	foreach (i; 0..2) guns ~= () => i;
	foreach (i; 0..2) writeln (guns[i] ());  // 1 and 1, why?

	int delegate () [] huns;
	foreach (i; 0..2) {
		immutable int j = i;
		huns ~= () => j;
	}
	foreach (i; 0..2) writeln (huns[i] ());  // 1 and 1, why?
}

In my real use case, the delegates actually get stored in 
different structs or classes instead of a single array, and 
instead of returning 0 and 1, they call another function with 
argument 0 and 1, respectively.
Also, the number of delegates to create is known only at runtime.
However, I believe that won't be a problem once I grasp how to do 
this basic example.

So, why do delegates of guns[] and huns[] all return 1, and how 
to correctly reproduce the behavior of funs[] while populating it 
in a loop?

Ivan Kazmenko.



More information about the Digitalmars-d-learn mailing list