Closures and loop scope
Yota
yotaxp at thatGoogleMailThing.com
Thu Sep 19 09:39:13 PDT 2013
I just ran into the problem myself, and it really caught me off
guard.
import std.stdio, core.thread;
void main() {
foreach (i; 0..3) {
immutable ii = i; // Copy for good measure?
writeln("Main: ", ii);
auto t = new Thread({
writeln("Worker Start: ", ii);
Thread.sleep(dur!"msecs"(1));
writeln("Worker End: ", ii);
});
t.start();
}
}
Output:
Main: 0
Main: 1
Worker Start: 1
Main: 2
Worker Start: 2
Worker Start: 2
Worker End: 2
Worker End: 2
Worker End: 2
I caught on that the problem has to do with capturing stack
variables that are going out of scope, but this is resulting a
mutating immutable, without subverting the type system, and
without a complaint from the compiler. (First iteration, 'ii' is
captured while 0. The captured 'ii' is then 1 when the thread
begins, and 2 when it ends.) This seems like a major problem in
the type system, without even being a problem with the type
system.
The following was suggested as a means to capture by value:
On Tuesday, 4 June 2013 at 19:19:57 UTC, Idan Arye wrote:
> 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 indeed appears to work, but... why? From the looks of it,
it is doing the exact same thing. It is capturing a local stack
variable that immediately goes out of scope. Why isn't the extra
stack frame being overwritten each iteration? Also, that
anonymous function really looks like something that the compiler
would inline, so is there even an extra stack frame? I think I
see why Idan called it a 'hackaround'.
I gather two things from this:
1. We really need a legit way to force capture-by-value on a
variable by variable basis. (Unless there's already another way.
Anyone?)
2. Why are immutable local variables not ALWAYS captured by
value? It's not like they are expected to change at all in the
first place. This would at least fix the promise that the type
system makes regarding immutables. (Well... until pointers to
immutables on the stack come into play.)
More information about the Digitalmars-d
mailing list