www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to declare function with the same call signature as another?

reply Tofu Ninja <joeyemmons yahoo.com> writes:
I feel like this should be simple but I can't seem to figure it 
out. How do I declare a function to have the same call signature 
as another function/callable type?

Like if I have:

alias Sig = int function(int x, int y);

How do I define a function such that it will have the same call 
signature as Sig? How do I take into account all the extra stuff 
that can go into a function signature like the argument 
attributes and the return type attributes etc.?

Another way to phrase this question would be, how do I pass a 
function signature into a template and actually define functions 
with it?

Related question, if I have Sig, how would I define DeltaSig to 
be exactly the same as Sig but with an extra parameter at the 
start or end of the parameter list?

Thanks :)
Nov 20 2016
next sibling parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Sunday, 20 November 2016 at 11:19:24 UTC, Tofu Ninja wrote:
 I feel like this should be simple but I can't seem to figure it 
 out. How do I declare a function to have the same call 
 signature as another function/callable type?

 Like if I have:

 alias Sig = int function(int x, int y);

 How do I define a function such that it will have the same call 
 signature as Sig? How do I take into account all the extra 
 stuff that can go into a function signature like the argument 
 attributes and the return type attributes etc.?

 Another way to phrase this question would be, how do I pass a 
 function signature into a template and actually define 
 functions with it?

 Related question, if I have Sig, how would I define DeltaSig to 
 be exactly the same as Sig but with an extra parameter at the 
 start or end of the parameter list?

 Thanks :)
import std.traits; ReturnType!Sig func(Parameters!Sig args) { //... }
Nov 20 2016
parent reply Tofu Ninja <joeyemmons yahoo.com> writes:
On Sunday, 20 November 2016 at 11:23:37 UTC, Nicholas Wilson 
wrote:
 On Sunday, 20 November 2016 at 11:19:24 UTC, Tofu Ninja wrote:
 I feel like this should be simple but I can't seem to figure 
 it out. How do I declare a function to have the same call 
 signature as another function/callable type?

 Like if I have:

 alias Sig = int function(int x, int y);

 How do I define a function such that it will have the same 
 call signature as Sig? How do I take into account all the 
 extra stuff that can go into a function signature like the 
 argument attributes and the return type attributes etc.?

 Another way to phrase this question would be, how do I pass a 
 function signature into a template and actually define 
 functions with it?

 Related question, if I have Sig, how would I define DeltaSig 
 to be exactly the same as Sig but with an extra parameter at 
 the start or end of the parameter list?

 Thanks :)
import std.traits; ReturnType!Sig func(Parameters!Sig args) { //... }
This does not seem to account for return type attributes or function attributes. Eg: alias Sig = ref int function() nogc; ReturnType!Sig func(Parameters!Sig args) { // func is missing ref on return type and is not nogc static int g; return g; } How should I account for these things?
Nov 20 2016
parent reply Tofu Ninja <joeyemmons yahoo.com> writes:
On Sunday, 20 November 2016 at 11:52:01 UTC, Tofu Ninja wrote:
 ...
Also does not include function linkage :/
Nov 20 2016
parent reply Tofu Ninja <joeyemmons yahoo.com> writes:
On Sunday, 20 November 2016 at 12:06:15 UTC, Tofu Ninja wrote:
 On Sunday, 20 November 2016 at 11:52:01 UTC, Tofu Ninja wrote:
 ...
Also does not include function linkage :/
Because of the lack of response, I am going to guess there is no way to do this cleanly. Guess I am going to have to break out the trusty old mixin to get this working. Also wtf is this... how does this even make sense? template make_ref(T){ static if(is(void delegate(ref T) ftype == delegate) && is(ftype P == function)) alias make_ref = P; else static assert(false); } void main(){ import std.stdio; writeln(make_ref!int.stringof); // (ref int) } What is a (ref int)? A tuple with "ref int" as its only member? Since when is ref int a type?
Nov 23 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Wednesday, 23 November 2016 at 22:14:25 UTC, Tofu Ninja wrote:
 What is a (ref int)? A tuple with "ref int" as its only member? 
 Since when is ref int a type?
it is "type with modifier", like "const int" or "immutable int".
Nov 23 2016
parent reply Tofu Ninja <joeyemmons yahoo.com> writes:
On Wednesday, 23 November 2016 at 22:19:28 UTC, ketmar wrote:
 On Wednesday, 23 November 2016 at 22:14:25 UTC, Tofu Ninja 
 wrote:
 What is a (ref int)? A tuple with "ref int" as its only 
 member? Since when is ref int a type?
it is "type with modifier", like "const int" or "immutable int".
Since when has ref been a type qualifier? It has always been a parameter/function attribute.
Nov 23 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Wednesday, 23 November 2016 at 22:28:57 UTC, Tofu Ninja wrote:
 On Wednesday, 23 November 2016 at 22:19:28 UTC, ketmar wrote:
 On Wednesday, 23 November 2016 at 22:14:25 UTC, Tofu Ninja 
 wrote:
 What is a (ref int)? A tuple with "ref int" as its only 
 member? Since when is ref int a type?
it is "type with modifier", like "const int" or "immutable int".
Since when has ref been a type qualifier? It has always been a parameter/function attribute.
which is technically type qualifier. it just forbidden (in grammar) to use it anywhere except arg declaration.
Nov 23 2016
parent reply Tofu Ninja <joeyemmons yahoo.com> writes:
On Wednesday, 23 November 2016 at 22:48:17 UTC, ketmar wrote:
 On Wednesday, 23 November 2016 at 22:28:57 UTC, Tofu Ninja 
 wrote:
 On Wednesday, 23 November 2016 at 22:19:28 UTC, ketmar wrote:
 On Wednesday, 23 November 2016 at 22:14:25 UTC, Tofu Ninja 
 wrote:
 What is a (ref int)? A tuple with "ref int" as its only 
 member? Since when is ref int a type?
it is "type with modifier", like "const int" or "immutable int".
Since when has ref been a type qualifier? It has always been a parameter/function attribute.
which is technically type qualifier. it just forbidden (in grammar) to use it anywhere except arg declaration.
Maybe the compiler sees it as a type qualifier, but it is not listed as a type qualifier and does not behave like a type qualifier in any sense. For example typeof will never return "ref int" but will return "const int", auto will never infer ref but can infer const, you can pass const(int) into a template but can never pass ref(int) into a template(even with that hack I posted before, the ref gets striped). Being able to get an alias to (ref int) seems like a bug.
Nov 23 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Wednesday, 23 November 2016 at 23:02:30 UTC, Tofu Ninja wrote:
 Being able to get an alias to (ref int) seems like a bug.
you are unable to alias it, `ref` will be erased on aliasing. the only way to retain it is to have a tuple with it. that trick aliases *function* *argument* *tuple*, not a single type. yeah, `ref` is very special beast. but it is still type modifier. ;-)
Nov 23 2016
parent reply Tofu Ninja <joeyemmons yahoo.com> writes:
On Wednesday, 23 November 2016 at 23:21:53 UTC, ketmar wrote:
 On Wednesday, 23 November 2016 at 23:02:30 UTC, Tofu Ninja 
 wrote:
 Being able to get an alias to (ref int) seems like a bug.
you are unable to alias it, `ref` will be erased on aliasing. the only way to retain it is to have a tuple with it. that trick aliases *function* *argument* *tuple*, not a single type. yeah, `ref` is very special beast. but it is still type modifier. ;-)
Unless I can write "alias refint = ref int;", this should not be a feature at all... how did anyone think this is a good idea. Seriously I used to love D but now it's just a mess of hacks...
Nov 23 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Thursday, 24 November 2016 at 00:04:51 UTC, Tofu Ninja wrote:
 On Wednesday, 23 November 2016 at 23:21:53 UTC, ketmar wrote:
 On Wednesday, 23 November 2016 at 23:02:30 UTC, Tofu Ninja 
 wrote:
 Being able to get an alias to (ref int) seems like a bug.
you are unable to alias it, `ref` will be erased on aliasing. the only way to retain it is to have a tuple with it. that trick aliases *function* *argument* *tuple*, not a single type. yeah, `ref` is very special beast. but it is still type modifier. ;-)
Unless I can write "alias refint = ref int;", this should not be a feature at all... how did anyone think this is a good idea. Seriously I used to love D but now it's just a mess of hacks...
either this, or you won't be able to replicate function with it's exact args; you won't be able to even check if some arg is ref. but not having `ref int` as a valid type declaration has it's reasons.
Nov 23 2016
parent reply Tofu Ninja <joeyemmons yahoo.com> writes:
On Thursday, 24 November 2016 at 00:15:07 UTC, ketmar wrote:
 On Thursday, 24 November 2016 at 00:04:51 UTC, Tofu Ninja wrote:
 On Wednesday, 23 November 2016 at 23:21:53 UTC, ketmar wrote:
 On Wednesday, 23 November 2016 at 23:02:30 UTC, Tofu Ninja 
 wrote:
 Being able to get an alias to (ref int) seems like a bug.
you are unable to alias it, `ref` will be erased on aliasing. the only way to retain it is to have a tuple with it. that trick aliases *function* *argument* *tuple*, not a single type. yeah, `ref` is very special beast. but it is still type modifier. ;-)
Unless I can write "alias refint = ref int;", this should not be a feature at all... how did anyone think this is a good idea. Seriously I used to love D but now it's just a mess of hacks...
either this, or you won't be able to replicate function with it's exact args; you won't be able to even check if some arg is ref. but not having `ref int` as a valid type declaration has it's reasons.
You still can't replicate a function with this. No way to replicate or even know if a parameter is variadic. No way to replicate the ref on the return. No way to replicate the linkage or attributes of the function. This is a hack that solves nothing.
Nov 23 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Thursday, 24 November 2016 at 00:19:04 UTC, Tofu Ninja wrote:
 You still can't replicate a function with this.
you can, by using std.traits and string mixins.
Nov 23 2016
parent reply Tofu Ninja <joeyemmons yahoo.com> writes:
On Thursday, 24 November 2016 at 00:36:54 UTC, ketmar wrote:
 On Thursday, 24 November 2016 at 00:19:04 UTC, Tofu Ninja wrote:
 You still can't replicate a function with this.
you can, by using std.traits and string mixins.
Even with std.traits, you can't know which arguments are variadic. The only way to actually replicate a function is with string mixins and parsing the stringof of the function you want to replicate. This (ref int) thing does not help one bit and will only trick people into thinking they are properly replicating the call signature when they are not.
Nov 23 2016
parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Thursday, 24 November 2016 at 00:51:01 UTC, Tofu Ninja wrote:
 Even with std.traits, you can't know which arguments are 
 variadic.
sure, you can. see http://dpldocs.info/experimental-docs/std.traits.variadicFunctionStyle.html that will return variadic style. and the only argument that can be variadic is last. it is enough to reconstruct the signature.
Nov 23 2016
parent reply Tofu Ninja <joeyemmons yahoo.com> writes:
On Thursday, 24 November 2016 at 02:11:21 UTC, ketmar wrote:
 On Thursday, 24 November 2016 at 00:51:01 UTC, Tofu Ninja wrote:
 Even with std.traits, you can't know which arguments are 
 variadic.
sure, you can. see http://dpldocs.info/experimental-docs/std.traits.variadicFunctionStyle.html that will return variadic style. and the only argument that can be variadic is last. it is enough to reconstruct the signature.
Oh well that is my bad, for some reason I was under the impression that there could be more than one typesafe variadic. Still I think the way all of this currently works is very misleading, certainly there is lots of code out there trying to replicate call signatures but are doing it wrong. Having Parameters!(fun) capture things like ref is only going to mislead people(like me!) into thinking it is enough.
Nov 23 2016
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Thursday, 24 November 2016 at 02:52:05 UTC, Tofu Ninja wrote:
 On Thursday, 24 November 2016 at 02:11:21 UTC, ketmar wrote:
 On Thursday, 24 November 2016 at 00:51:01 UTC, Tofu Ninja 
 wrote:
 Even with std.traits, you can't know which arguments are 
 variadic.
sure, you can. see http://dpldocs.info/experimental-docs/std.traits.variadicFunctionStyle.html that will return variadic style. and the only argument that can be variadic is last. it is enough to reconstruct the signature.
Oh well that is my bad, for some reason I was under the impression that there could be more than one typesafe variadic. Still I think the way all of this currently works is very misleading, certainly there is lots of code out there trying to replicate call signatures but are doing it wrong. Having Parameters!(fun) capture things like ref is only going to mislead people(like me!) into thinking it is enough.
here i agree. ;-) still, i can't think out a better way to do that. if you have any solid (or at least semi-solid ;-) ideas, feel free to start a new thread, we love bikeshedding! ;-)
Nov 23 2016
prev sibling parent Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Sunday, 20 November 2016 at 11:19:24 UTC, Tofu Ninja wrote:
 I feel like this should be simple but I can't seem to figure it 
 out. How do I declare a function to have the same call 
 signature as another function/callable type?

 Like if I have:

 alias Sig = int function(int x, int y);

 How do I define a function such that it will have the same call 
 signature as Sig? How do I take into account all the extra 
 stuff that can go into a function signature like the argument 
 attributes and the return type attributes etc.?

 Another way to phrase this question would be, how do I pass a 
 function signature into a template and actually define 
 functions with it?

 Related question, if I have Sig, how would I define DeltaSig to 
 be exactly the same as Sig but with an extra parameter at the 
 start or end of the parameter list?

 Thanks :)
Or if you want additional parameters. ReturnType!Sig func(int paramBefore, Parameters!Sig args, int paramAfter) { ... }
Nov 20 2016