digitalmars.D.learn - Copying a variable state in a delegate literal definition
- Andrej Mitrovic <andrej.mitrovich gmail.com> Sep 02 2011
- David Nadlinger <see klickverbot.at> Sep 02 2011
- "Steven Schveighoffer" <schveiguy yahoo.com> Sep 02 2011
- Andrej Mitrovic <andrej.mitrovich gmail.com> Sep 02 2011
- "Daniel Murphy" <yebblies nospamgmail.com> Sep 02 2011
So I have this code right here (semi-pseudocode) inside a "MenuBar" widget:
void showMenu(index menuIndex) { }
void appendMenuButton()
{
static size_t menuIndex;
// create menu button, and then:
button.connect!(Signal.MouseClick) = { this.showMenu(menuIndex); };
menuIndex++;
}
button is a newly constructed widget object, Signal is just an enum.
Inside of my Widget class I have this:
void delegate()[] clickHandlers;
property void connect(Signal signal)(void delegate() dg)
{
static if (signal == Signal.MouseClick)
clickHandlers ~= dg;
else
// ...
}
void onClicked()
{
foreach (handler; clickHandlers)
{
handler();
}
}
So far so good. This works except for the following quirk:
button.connect!(Signal.MouseClick) = { this.showMenu(menuIndex); };
Inside this lambda menuIndex is accessed through that frame pointer
when the lambda is called. But I actually want a *copy* of menuIndex
at the definition site. Because as I call appendMenuButton() numerous
times, menuIndex is increased, so if I do this:
menu.appendMenuButton();
menu.appendMenuButton();
{ this.showMenu(menuIndex); }; becomes:
{ this.showMenu(2); };
when it is called. I can't use a function literal instead of a
delegate literal because I want to have access to "this.showMenu", but
I want a copy of menuIndex. I've tried this:
{ size_t index = menuIndex; writeln(index); }
However that doesn't copy the state either, it initializes index with
the menuIndex in the frame pointer when the literal is called.
So how can I selectively copy the state of some variables at the site
of the definition of a delegate literal?
Sep 02 2011
On 9/2/11 8:29 PM, Andrej Mitrovic wrote:So how can I selectively copy the state of some variables at the site of the definition of a delegate literal?
You can try introducing a new frame using a immediately executed delegate literal: button.connect!(Signal.MouseClick) = { auto index = menuIndex; return { this.showMenu(index); }; }(); David
Sep 02 2011
On Fri, 02 Sep 2011 14:29:18 -0400, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:So I have this code right here (semi-pseudocode) inside a "MenuBar" widget: void showMenu(index menuIndex) { } void appendMenuButton() { static size_t menuIndex; // create menu button, and then: button.connect!(Signal.MouseClick) = { this.showMenu(menuIndex); }; menuIndex++; } button is a newly constructed widget object, Signal is just an enum. Inside of my Widget class I have this: void delegate()[] clickHandlers; property void connect(Signal signal)(void delegate() dg) { static if (signal == Signal.MouseClick) clickHandlers ~= dg; else // ... } void onClicked() { foreach (handler; clickHandlers) { handler(); } } So far so good. This works except for the following quirk: button.connect!(Signal.MouseClick) = { this.showMenu(menuIndex); }; Inside this lambda menuIndex is accessed through that frame pointer when the lambda is called. But I actually want a *copy* of menuIndex at the definition site. Because as I call appendMenuButton() numerous times, menuIndex is increased, so if I do this: menu.appendMenuButton(); menu.appendMenuButton(); { this.showMenu(menuIndex); }; becomes: { this.showMenu(2); }; when it is called. I can't use a function literal instead of a delegate literal because I want to have access to "this.showMenu", but I want a copy of menuIndex. I've tried this: { size_t index = menuIndex; writeln(index); } However that doesn't copy the state either, it initializes index with the menuIndex in the frame pointer when the literal is called. So how can I selectively copy the state of some variables at the site of the definition of a delegate literal?
Am I missing something, or is it this simple? void appendMenuButton() { static size_t menuIndex; auto frameIndex = menuIndex++; button.connect!(Signal.MouseClick) = { this.showMenu(frameIndex); }; } -Steve
Sep 02 2011
On 9/2/11, Steven Schveighoffer <schveiguy yahoo.com> wrote:Am I missing something, or is it this simple? void appendMenuButton() { static size_t menuIndex; auto frameIndex = menuIndex++; button.connect!(Signal.MouseClick) = { this.showMenu(frameIndex); }; } -Steve
Actually It *is* that simple. Which is odd because I swear I've tried it once but it didn't work, and now it works again. Something has to be messing with the compiler or my brain!
Sep 02 2011
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message news:mailman.2651.1315000369.14074.digitalmars-d-learn puremagic.com...On 9/2/11, Steven Schveighoffer <schveiguy yahoo.com> wrote:Am I missing something, or is it this simple? void appendMenuButton() { static size_t menuIndex; auto frameIndex = menuIndex++; button.connect!(Signal.MouseClick) = { this.showMenu(frameIndex); }; } -Steve
Actually It *is* that simple. Which is odd because I swear I've tried it once but it didn't work, and now it works again. Something has to be messing with the compiler or my brain!
It won't work when loops are involved. In that case I usually use: foreach(i; ...) (int i){ something = { delegate that uses i like a constant }; }(i);
Sep 02 2011









David Nadlinger <see klickverbot.at> 