digitalmars.D.learn - Get parent function of nested delegate
- Anonymouse (33/33) Feb 15 I want to get a reference to a parent function from inside a
- Inkrementator (22/23) Feb 16 As a workaround, you can define a useless symbol and get the
- Jonathan M Davis (21/54) Mar 17 If I had to guess, the problem is that when you're passing the name of t...
- Jonathan M Davis (20/81) Mar 17 Actually, when I went to create an enhancement request for
I want to get a reference to a parent function from inside a nested function. I need it for `getUDAs!(parentFunction, attribute)`. `__traits(parent, mixin(__FUNCTION__))` works inside the parent function and gives me the module, but `mixin(__FUNCTION__)` alone inside the nested function immediately errors. ```d module foo; void bar(string s, int i) { assert(__FUNCTION__ == "foo.bar"); alias parentModule = __traits(parent, mixin(__FUNCTION__)); assert(is(parentModule == module)); void dg() { assert(__FUNCTION__ == "foo.bar.dg"); alias parentFunction = __traits(parent, mixin(__FUNCTION__)); } } void main() {} ``` ``` onlineapp.d(12): Error: function `bar` is not callable using argument types `()` onlineapp.d(12): too few arguments, expected 2, got 0 onlineapp.d(3): `foo.bar(string s, int i)` declared here ``` So `mixin(__FUNCTION__)` seems to be trying to call the parent function rather than giving me the symbol of the nested one, like `foo.bar().dg`. I tried making it `mixin("&" ~ __FUNCTION__)` but it did not help. How can I make this work?
Feb 15
On Sunday, 16 February 2025 at 07:38:09 UTC, Anonymouse wrote:How can I make this work?As a workaround, you can define a useless symbol and get the parent of that. ``` module foo; void bar(string s, int i) { assert(__FUNCTION__ == "foo.bar"); alias parentModule = __traits(parent, mixin(__FUNCTION__)); assert(is(parentModule == module)); void dg() { assert(__FUNCTION__ == "foo.bar.dg"); enum n = 0; alias parentFunction = __traits(parent, __traits(parent, n)); pragma(msg, __traits(identifier, parentFunction)); // bar pragma(msg, __traits(identifier, __traits(parent, n))); // dg } } void main() {} ```
Feb 16
On Sunday, February 16, 2025 12:38:09 AM MDT Anonymouse via Digitalmars-d-learn wrote:I want to get a reference to a parent function from inside a nested function. I need it for `getUDAs!(parentFunction, attribute)`. `__traits(parent, mixin(__FUNCTION__))` works inside the parent function and gives me the module, but `mixin(__FUNCTION__)` alone inside the nested function immediately errors. ```d module foo; void bar(string s, int i) { assert(__FUNCTION__ == "foo.bar"); alias parentModule = __traits(parent, mixin(__FUNCTION__)); assert(is(parentModule == module)); void dg() { assert(__FUNCTION__ == "foo.bar.dg"); alias parentFunction = __traits(parent, mixin(__FUNCTION__)); } } void main() {} ``` ``` onlineapp.d(12): Error: function `bar` is not callable using argument types `()` onlineapp.d(12): too few arguments, expected 2, got 0 onlineapp.d(3): `foo.bar(string s, int i)` declared here ``` So `mixin(__FUNCTION__)` seems to be trying to call the parent function rather than giving me the symbol of the nested one, like `foo.bar().dg`. I tried making it `mixin("&" ~ __FUNCTION__)` but it did not help. How can I make this work?If I had to guess, the problem is that when you're passing the name of the function to __traits(parent, ...), it's grabbing that symbol via the normal lookup rules, meaning that the visibility rules apply, and nested functions are not visible from outside the function. Now, you're inside the function in the example, but since you don't normally use the full path for a nested function when using it, the compiler probably isn't even set up to do so. I would guess that it was simply never thought of. Really, what would be ideal here would be something like __FUNCTION_SYMBOL__ which gave the symbol of the function rather than its name as a string, since that would bypass this whole issue (as well as negate the need to use a mixin to get the symbol for the function). However, there is a pretty simple workaround. Just get the symbol from within the parent function instead of within the nested function, e.g. alias parentFunction = mixin(__FUNCTION__); void dg() { // access parentFunction here } It even works if the nested function is static. - Jonathan M Davis
Mar 17
On Monday, March 17, 2025 6:28:19 PM MDT Jonathan M Davis via Digitalmars-d-learn wrote:On Sunday, February 16, 2025 12:38:09 AM MDT Anonymouse via Digitalmars-d-learn wrote:Actually, when I went to create an enhancement request for __FUNCTION_SYMBOL__ and did some digging to see what already exists, I found out about this trick: __traits(parent, {}) will give you the symbol for the current function, making it similar to __traits(parent, mixin(__FUNCTION__)); except for any of the symbol look-up issues. So, if you want to get the parent of nested function, you can just do __traits(parent, __traits(parent, {})) I'd still probably get the symbol for the parent function inside the function and create an alias to it which the nested function could use rather than looking it up in the nested function, because it requires only a single trait instead of two, but this seems like a cleaner approach to me than using mixin(__FUNCTION__) - especially since now that I think about it, you could actually get the wrong function with mixin(__FUNCTION__) if the function is overloaded - in that case, you'd need __traits(getOverloads, ...), and you'd need to somehow know which the correct overload was, which seems like it would be very error-prone. - Jonathan M DavisI want to get a reference to a parent function from inside a nested function. I need it for `getUDAs!(parentFunction, attribute)`. `__traits(parent, mixin(__FUNCTION__))` works inside the parent function and gives me the module, but `mixin(__FUNCTION__)` alone inside the nested function immediately errors. ```d module foo; void bar(string s, int i) { assert(__FUNCTION__ == "foo.bar"); alias parentModule = __traits(parent, mixin(__FUNCTION__)); assert(is(parentModule == module)); void dg() { assert(__FUNCTION__ == "foo.bar.dg"); alias parentFunction = __traits(parent, mixin(__FUNCTION__)); } } void main() {} ``` ``` onlineapp.d(12): Error: function `bar` is not callable using argument types `()` onlineapp.d(12): too few arguments, expected 2, got 0 onlineapp.d(3): `foo.bar(string s, int i)` declared here ``` So `mixin(__FUNCTION__)` seems to be trying to call the parent function rather than giving me the symbol of the nested one, like `foo.bar().dg`. I tried making it `mixin("&" ~ __FUNCTION__)` but it did not help. How can I make this work?If I had to guess, the problem is that when you're passing the name of the function to __traits(parent, ...), it's grabbing that symbol via the normal lookup rules, meaning that the visibility rules apply, and nested functions are not visible from outside the function. Now, you're inside the function in the example, but since you don't normally use the full path for a nested function when using it, the compiler probably isn't even set up to do so. I would guess that it was simply never thought of. Really, what would be ideal here would be something like __FUNCTION_SYMBOL__ which gave the symbol of the function rather than its name as a string, since that would bypass this whole issue (as well as negate the need to use a mixin to get the symbol for the function). However, there is a pretty simple workaround. Just get the symbol from within the parent function instead of within the nested function, e.g. alias parentFunction = mixin(__FUNCTION__); void dg() { // access parentFunction here } It even works if the nested function is static.
Mar 17