www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - IFTI reflection would be nice

reply Adam D. Ruppe <destructionator gmail.com> writes:
Another useful thing to have would be "given this argument set to 
a function, give me the function that would be called".

This would do implicit function template instantiation and 
overload resolution, but yield the function instead of the return 
value.

Imagine:

void foo(int a) {}
void foo(string b) {}


I want to get the address of foo(string). How do you do that 
right now? Well, you have to loop over overloads and check the 
types. What a pain, but at least doable.

But wouldn't it be cool if you could do

&__functionOf(foo("foo"))

Where the __functionOf is the magic.


So far, this is kinda just a convenience, but now imagine the 
case of a template. Even if template reflection worked, you'd 
need to figure out the template arguments and that can be 
basically impossible given the conversions and specializations.

Then

&__functionOf(writeln("bar"))

for example would give a void function(string). There you can do 
`&writeln!string`


And in cases more complex than that, the compiler's logic need 
not be reimplemented in user cde.
Jul 26 2020
next sibling parent reply Avrina <avrina12309412342 gmail.com> writes:
On Sunday, 26 July 2020 at 13:20:40 UTC, Adam D. Ruppe wrote:
 Imagine:

 void foo(int a) {}
 void foo(string b) {}


 I want to get the address of foo(string). How do you do that 
 right now? Well, you have to loop over overloads and check the 
 types. What a pain, but at least doable.

 But wouldn't it be cool if you could do

 &__functionOf(foo("foo"))

 Where the __functionOf is the magic.
You can just use cast() right now to get the overload you want. https://run.dlang.io/is/n76kt3 import std.stdio; void foo(string) { writeln("foo(string)"); } void foo(int) { writeln("foo(int)"); } void main() { auto a = cast(void function(string))&foo; auto b = cast(void function(int))&foo; a(""); b(10); }
Jul 26 2020
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 26 July 2020 at 14:03:31 UTC, Avrina wrote:
 You can just use cast() right now to get the overload you want.
Wow, I actually did not know that. But, cast is always bleh - try `auto a = cast(void function(float))&foo;`... then it calls the string one in both cases, yikes... I can't remember the example that got me thinking about this a couple weeks ago, but it was a template that could *only* be used with IFTI. That's my main concern, but overload selection without the pitfalls of cast would be a very nice bonus too.
Jul 26 2020
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/26/20 12:36 PM, Adam D. Ruppe wrote:
 On Sunday, 26 July 2020 at 14:03:31 UTC, Avrina wrote:
 You can just use cast() right now to get the overload you want.
Wow, I actually did not know that. But, cast is always bleh - try `auto a = cast(void function(float))&foo;`... then it calls the string one in both cases, yikes... I can't remember the example that got me thinking about this a couple weeks ago, but it was a template that could *only* be used with IFTI. That's my main concern, but overload selection without the pitfalls of cast would be a very nice bonus too.
Maybe my query here? This would solve my issue. https://forum.dlang.org/post/rd0d29$8bj$1 digitalmars.com -Steve
Jul 26 2020
prev sibling parent reply Avrina <avrina12309412342 gmail.com> writes:
On Sunday, 26 July 2020 at 16:36:43 UTC, Adam D. Ruppe wrote:
 On Sunday, 26 July 2020 at 14:03:31 UTC, Avrina wrote:
 You can just use cast() right now to get the overload you want.
Wow, I actually did not know that. But, cast is always bleh - try `auto a = cast(void function(float))&foo;`... then it calls the string one in both cases, yikes... I can't remember the example that got me thinking about this a couple weeks ago, but it was a template that could *only* be used with IFTI. That's my main concern, but overload selection without the pitfalls of cast would be a very nice bonus too.
That should probably be an error, there's no reason that should work at all. It can't select one based on the type, it shouldn't select any, and it looks like it just selects the first one. You can do this which is more type safe, but again, it should an ambiguous error. There's no reason it should be picking string over int. import std.stdio; void foo(string) { writeln("foo(string)"); } void foo(int) { writeln("foo(int)"); } void main() { void function(float) a = &foo; } Error: cannot implicitly convert expression & foo of type void function(string _param_0) to void function(float)
Jul 26 2020
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Sunday, 26 July 2020 at 17:30:40 UTC, Avrina wrote:
 On Sunday, 26 July 2020 at 16:36:43 UTC, Adam D. Ruppe wrote:
 [...]
That should probably be an error, there's no reason that should work at all. It can't select one based on the type, it shouldn't select any, and it looks like it just selects the first one. You can do this which is more type safe, but again, it should an ambiguous error. There's no reason it should be picking string over int. import std.stdio; void foo(string) { writeln("foo(string)"); } void foo(int) { writeln("foo(int)"); } void main() { void function(float) a = &foo; } Error: cannot implicitly convert expression & foo of type void function(string _param_0) to void function(float)
The reason is the other of definition. But the int overload first and the error should go away.
Jul 26 2020
prev sibling parent user1234 <user1234 12.de> writes:
On Sunday, 26 July 2020 at 14:03:31 UTC, Avrina wrote:
 On Sunday, 26 July 2020 at 13:20:40 UTC, Adam D. Ruppe wrote:
 Imagine:

 void foo(int a) {}
 void foo(string b) {}


 I want to get the address of foo(string). How do you do that 
 right now? Well, you have to loop over overloads and check the 
 types. What a pain, but at least doable.

 But wouldn't it be cool if you could do

 &__functionOf(foo("foo"))

 Where the __functionOf is the magic.
You can just use cast() right now to get the overload you want. https://run.dlang.io/is/n76kt3 import std.stdio; void foo(string) { writeln("foo(string)"); } void foo(int) { writeln("foo(int)"); } void main() { auto a = cast(void function(string))&foo; auto b = cast(void function(int))&foo; a(""); b(10); }
OMG excellent, where have you learnt this ancient secret of the gods ?
Jul 28 2020
prev sibling next sibling parent reply Jean-Louis Leroy <jl leroy.nyc> writes:
On Sunday, 26 July 2020 at 13:20:40 UTC, Adam D. Ruppe wrote:
 Another useful thing to have would be "given this argument set 
 to a function, give me the function that would be called".

 This would do implicit function template instantiation and 
 overload resolution, but yield the function instead of the 
 return value.

 Imagine:

 void foo(int a) {}
 void foo(string b) {}


 I want to get the address of foo(string). How do you do that 
 right now? Well, you have to loop over overloads and check the 
 types. What a pain, but at least doable.

 But wouldn't it be cool if you could do

 &__functionOf(foo("foo"))

 Where the __functionOf is the magic.


 So far, this is kinda just a convenience, but now imagine the 
 case of a template. Even if template reflection worked, you'd 
 need to figure out the template arguments and that can be 
 basically impossible given the conversions and specializations.

 Then

 &__functionOf(writeln("bar"))

 for example would give a void function(string). There you can 
 do `&writeln!string`


 And in cases more complex than that, the compiler's logic need 
 not be reimplemented in user cde.
Or make an alias, rather than a function pointer. That would be more useful.
Jul 26 2020
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 26 July 2020 at 19:08:01 UTC, Jean-Louis Leroy wrote:
 Or make an alias, rather than a function pointer. That would be 
 more useful.
yeah my __functionOf would be an alias, then you can & it to get the function pointer.
Jul 26 2020
prev sibling parent Manu <turkeyman gmail.com> writes:
On Sun, Jul 26, 2020 at 11:25 PM Adam D. Ruppe via Digitalmars-d <
digitalmars-d puremagic.com> wrote:

 Another useful thing to have would be "given this argument set to
 a function, give me the function that would be called".

 This would do implicit function template instantiation and
 overload resolution, but yield the function instead of the return
 value.

 Imagine:

 void foo(int a) {}
 void foo(string b) {}


 I want to get the address of foo(string). How do you do that
 right now? Well, you have to loop over overloads and check the
 types. What a pain, but at least doable.

 But wouldn't it be cool if you could do

 &__functionOf(foo("foo"))

 Where the __functionOf is the magic.


 So far, this is kinda just a convenience, but now imagine the
 case of a template. Even if template reflection worked, you'd
 need to figure out the template arguments and that can be
 basically impossible given the conversions and specializations.

 Then

 &__functionOf(writeln("bar"))

 for example would give a void function(string). There you can do
 `&writeln!string`


 And in cases more complex than that, the compiler's logic need
 not be reimplemented in user cde.
Write a DIP! This is a very real reflection hole that I've struggled with before too. Trying to sample all the possibilities, and then mirror the complex logic that the compiler uses to select a function to call internally is not a problem that should exist in user-space, and the compiler rules are subject to change making maintenance tricky and extremely brittle. I'd suggest it might just be a __traits though, rather than introducing a new magic thing.
Jul 29 2020