digitalmars.D - Forcing closures to come on the stack
- Mehrdad (57/57) Aug 07 2011 I just made something I thought I'd share.
- Simen Kjaeraas (6/30) Aug 08 2011 You could use the 'scope' keyword, no?
- %u (2/3) Aug 08 2011 From what I've heard it's being deprecated/removed -- although I'd be
- Jonathan M Davis (5/9) Aug 08 2011 scope on function parameters is sticking around as are scoped statements...
I just made something I thought I'd share. It's great for those times when the compiler decides to randomly put a closure on the heap. The usage is pretty simple: int x = 5; auto adder5 = mixin(closure!x(q{(int a) { return a + x; }})); assert(adder5(10) == 15); It returns a callable struct whose body is the given string; the template parameters are the variables under closure (in this case, x). The generated code looks like (minus a little beautification on my part): (delegate(ref int x) { static struct State { int* px; property ref int x() { return *this.px; } auto opCall(int a) { return a + x; } } State tmp; tmp.px = &x; return tmp; })(x) So when you assign it to something, that something becomes a struct with opCall overloaded. You can then take the address of opCall on the struct, and you get a delegate. Thoughts? ---------------------------------------------- // Code: string closure(States...)(string argsAndBody) { string stateArgs = null, stateVars = null, stateProps = null, setStateVars = null; alias staticMap!(StringOf, States) VarNames; string varPtrs; alias staticMap!(TypeStringOf, States) TypeNames; foreach (i, varName; VarNames) { if (varPtrs != null) { varPtrs ~= ", "; } if (stateArgs != null) { stateArgs ~= ", "; } varPtrs ~= varName; stateArgs ~= "ref " ~ TypeNames[i] ~ " " ~ varName; stateVars ~= TypeNames[i] ~ "* ___p_" ~ varName ~ "; "; stateProps ~= " property ref " ~ TypeNames[i] ~ " " ~ varName ~ "() { return *this.___p_" ~ varName ~ "; } "; setStateVars ~= "___tmp.___p_" ~ varName ~ " = &" ~ varName ~ "; "; } return "(" ~ "delegate(" ~ stateArgs ~ ") { " ~ "static struct State { " ~ stateVars ~ "" ~ stateProps ~ "" ~ "auto opCall" ~ argsAndBody ~ "" ~ "} " ~ "State ___tmp; " ~ setStateVars ~ "return ___tmp; " ~"})(" ~ varPtrs ~ ")"; }
Aug 07 2011
On Mon, 08 Aug 2011 04:51:19 +0200, Mehrdad <wfunction hotmail.com> wrote:I just made something I thought I'd share. It's great for those times when the compiler decides to randomly put a closure on the heap. The usage is pretty simple: int x = 5; auto adder5 = mixin(closure!x(q{(int a) { return a + x; }})); assert(adder5(10) == 15); It returns a callable struct whose body is the given string; the template parameters are the variables under closure (in this case, x). The generated code looks like (minus a little beautification on my part): (delegate(ref int x) { static struct State { int* px; property ref int x() { return *this.px; } auto opCall(int a) { return a + x; } } State tmp; tmp.px = &x; return tmp; })(x) So when you assign it to something, that something becomes a struct with opCall overloaded. You can then take the address of opCall on the struct, and you get a delegate. Thoughts?You could use the 'scope' keyword, no? Upon perusal of the documentation, it seems this is nowhere mentioned, and a report may be in order. -- Simen
Aug 08 2011
You could use the 'scope' keyword, no?From what I've heard it's being deprecated/removed -- although I'd be glad to hear otherwise.
Aug 08 2011
scope on function parameters is sticking around as are scoped statements. What's going around is scoped local variables which put a class on the stack. std.typecons.Scoped is replacing it. scoped delegates are sticking around though. - Jonathan M DavisYou could use the 'scope' keyword, no?From what I've heard it's being deprecated/removed -- although I'd be glad to hear otherwise.
Aug 08 2011