digitalmars.D.bugs - [Issue 10822] New: Need a way to get the address of a lambda function from within its body
- d-bugmail puremagic.com (133/133) Aug 14 2013 http://d.puremagic.com/issues/show_bug.cgi?id=10822
- d-bugmail puremagic.com (10/11) Aug 14 2013 http://d.puremagic.com/issues/show_bug.cgi?id=10822
http://d.puremagic.com/issues/show_bug.cgi?id=10822 Summary: Need a way to get the address of a lambda function from within its body Product: D Version: D2 Platform: All OS/Version: All Status: NEW Severity: enhancement Priority: P2 Component: DMD AssignedTo: nobody puremagic.com ReportedBy: andrej.mitrovich gmail.com 15:33:58 PDT --- Currently there doesn't seem to be a way to retrieve the address of a lambda function. If for any reason you need to know the address of the lambda function /within/ the body of the lambda, you can't currently do this without assigning it to another variable. The use-case are signals. Here's a contrived example: ----- module test; import std.stdio; struct Signal { void connect(void delegate(int) func) { funcs ~= func; } void disconnect(void delegate(int) target) { foreach (idx, func; funcs) { if (func is target) { funcs = funcs[0 .. idx] ~ funcs[idx + 1 .. $]; break; } } } void emit(int i) { foreach (func; funcs) func(i); } void delegate(int)[] funcs; } void main() { Signal signal; void delegate(int) handler; handler = (int i) { stderr.writefln("handler called with %s", i); if (i == 2) { signal.disconnect(handler); // ok } }; signal.connect(handler); signal.emit(1); signal.emit(2); signal.emit(3); } ----- In 'main', the lambda function is assigned to a 'handler' variable. The lambda's body can then reference this variable if it needs to pass its address around. It uses this address to disconnect itself from a list of signal handlers. Do note however that using this code is only possible because the lambda is a delegate and not a function type! IOW, calling "signal.disconnect(handler)" would not be possible if the lambda was a function. If it was a function it wouldn't have access to the outer frame to get the value of 'handler', even though it is de-facto an address of itself. Of course using the 'signal' variable also forces the lambda to be a delegate, but that's not important. If we had a way to retrieve the address of a lambda from within the body of the lambda, we could both: 1) Avoid having to assign the lambda to a variable in order to retrieve the address from within the labmda body This would allow using code such as the following: ----- import std.stdio; // note1: changed to accept functions // note2: now passing a signal reference explicitly struct Signal { void connect(void function(ref Signal, int) func) { funcs ~= func; } void disconnect(void function(ref Signal, int) target) { foreach (idx, func; funcs) { if (func is target) { funcs = funcs[0 .. idx] ~ funcs[idx + 1 .. $]; break; } } } void emit(int i) { foreach (func; funcs) func(this, i); } void function(ref Signal, int)[] funcs; } void main() { Signal signal; // connect to anonymous function signal.connect((ref Signal theSignal, int i) { stderr.writefln("handler called with %s", i); if (i == 2) { // new trait: get the address of this lambda theSignal.disconnect(__traits(addressOfThis)); } }); signal.emit(1); signal.emit(2); signal.emit(3); // no longer calls the lambda } ----- I suppose __traits(addressOfThis) could also be useful in classes, to avoid having to use "cast(void*)this" or even the opCast-safe "*cast(void**)&this". -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 14 2013
http://d.puremagic.com/issues/show_bug.cgi?id=10822 15:38:16 PDT ---theSignal.disconnect(__traits(addressOfThis));I did just realize that addressOfThis would have to return a typed pointer (e.g. void delegate(...) or void function(...)) rather than a vanilla void*, so addressOfThis is likely a bad name. A better concept name might be a getThis trait, where the trait returns the typed reference. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Aug 14 2013