D2 closure and loop variables

Adam D. Ruppe destructionator at gmail.com
Sat Oct 31 17:52:05 PDT 2009


I'm trying to make a delegate thing in a loop and hit something that seemed intuitively wrong. Here's some short code that shows what I mean:

===
import std.stdio;

class A {
	this(void delegate() _a) {
		a = _a;
	}

	void run() { a(); }

	private void delegate() a;
}

void main() {
	auto list = ['a', 'b', 'c'];
	A[string] buttons;
	foreach(l; list) {
		buttons[l ~ "\n"] = new A( { writefln("%s", l); } );
	}

	auto a = readln();
	buttons[a].run;
}
===

What happens is no matter what key you press, you always get the output of "c", whereas at first glance, I'd expect it to echo back the same letter to you. This makes sense when thinking about it in terms of memory: the delegate accesses the memory that variable l had assigned to it, which was overwritten by later loop iterations.

But, while it makes sense when thinking about it, intuitively, I expected that loop variable to be copied over somewhere, so the delegate would be accessing its own private copy, not the pointer being overwritten by the loop.


Generally, if a delegate escapes any scope, I expect it to take a snapshot of  the stack it is referencing at that time to make its private copy at the time it passes the closing brace.


What I'm asking is:

a) Is my expectation wrong, or does that make sense?
b) If not wrong, should D be doing this now, or is this a bug?
and c) If it isn't a bug, should it be? Copying it on every loop iteration would have a definite performance penalty, so it isn't remotely free. Moreover, being able to reference variables that might change later can be likely a good thing:

[code]
SomeClass a;

foreach(item; collection)
  item.someDelegate = { a.doSomething;}

a = new SomeClass;
[/code]

If it make a private copy inside that loop, someDelegate would be looking at null the whole time, whereas with the current behaviour, this code works.

So changing it might not even be sane from that perspective.


What do you guys think?



More information about the Digitalmars-d mailing list