www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Trait or builtin that returns arguments passed to current function (if

reply Per =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
Adam, and like others including me, are longing for a 
trait/builtin [1] that returns the parameters passed to the 
function of the current scope (if any). Has such a thing been 
proposed previously?

[1] 
http://dpldocs.info/this-week-in-d/Blog.Posted_2021_07_26.html#on-my-wish-list
Sep 08
next sibling parent reply bauss <jj_1337 live.dk> writes:
On Wednesday, 8 September 2021 at 21:53:21 UTC, Per Nordlöw wrote:
 Adam, and like others including me, are longing for a 
 trait/builtin [1] that returns the parameters passed to the 
 function of the current scope (if any). Has such a thing been 
 proposed previously?

 [1] 
 http://dpldocs.info/this-week-in-d/Blog.Posted_2021_07_26.html#on-my-wish-list
While there isn't something directly that does it then it's fairly trivial to implement. All you have to do to use it then is calling: ```d mixin(__ARGUMENTS__); ``` Here is the implementation: ```d string __ARGUMENTS__(string fn = __FUNCTION__)() { import std.traits : ParameterIdentifierTuple; import std.array : join; mixin("enum parameterNames = [ParameterIdentifierTuple!(" ~ fn ~ ")];"); return "auto __arguments = [" ~ parameterNames.join(",") ~ "];"; } ``` Here is a working example: ```d string __ARGUMENTS__(string fn = __FUNCTION__)() { import std.traits : ParameterIdentifierTuple; import std.array : join; mixin("enum parameterNames = [ParameterIdentifierTuple!(" ~ fn ~ ")];"); return "auto __arguments = [" ~ parameterNames.join(",") ~ "];"; } void test(int x, int y) { import std.stdio; mixin(__ARGUMENTS__); auto c = __arguments[0]; auto d = __arguments[1]; writefln("%d %d", c, d); } void main() { test(1,2); } ``` Output: 1 2 But yeah it would be nice if we could have it built-in, which I don't think has been done.
Sep 09
next sibling parent reply Basile B. <b2.temp gmx.com> writes:
On Thursday, 9 September 2021 at 08:39:05 UTC, bauss wrote:
 [...]
 Here is a working example:

 ```d
 string __ARGUMENTS__(string fn = __FUNCTION__)()
 {
     import std.traits : ParameterIdentifierTuple;
     import std.array : join;

     mixin("enum parameterNames = [ParameterIdentifierTuple!(" ~ 
 fn ~ ")];");

     return "auto __arguments = [" ~ parameterNames.join(",") ~ 
 "];";
 }

 void test(int x, int y)
 {
     import std.stdio;

     mixin(__ARGUMENTS__);

     auto c = __arguments[0];
     auto d = __arguments[1];

     writefln("%d %d", c, d);
 }

 void main()
 {
     test(1,2);
 }
 ```
 Output:
 1 2
Nice.
 But yeah it would be nice if we could have it built-in, which I 
 don't think has been done.
That's a contemporary D question that often comes in conversations: should "feature x" be a builtin or should "feature x" be made using metaprog... Is this used often ? is the metaprog version slow ?
Sep 09
parent reply Dennis <dkorpel gmail.com> writes:
On Thursday, 9 September 2021 at 10:14:03 UTC, Basile B. wrote:
 That's a contemporary D question that often comes in 
 conversations: should "feature x" be a builtin or should 
 "feature x" be made using metaprog...

 Is this used often ? is the metaprog version slow ?
Add "Is the metaprog version robust?". The given example doesn't work with `test(T...)(T args)`, doesn't work with `scope` parameters, doesn't work with non-copyable `ref` parameters, etc. I know it's a proof of concept, but I'm not sure a seamless library solution is even possible with how many complexities there are with all kinds of variadic arguments and storage classes D has.
Sep 09
parent reply Basile B. <b2.temp gmx.com> writes:
On Thursday, 9 September 2021 at 11:45:55 UTC, Dennis wrote:
 On Thursday, 9 September 2021 at 10:14:03 UTC, Basile B. wrote:
 That's a contemporary D question that often comes in 
 conversations: should "feature x" be a builtin or should 
 "feature x" be made using metaprog...

 Is this used often ? is the metaprog version slow ?
Add "Is the metaprog version robust?". The given example doesn't work with `test(T...)(T args)`, doesn't work with `scope` parameters, doesn't work with non-copyable `ref` parameters, etc. I know it's a proof of concept, but I'm not sure a seamless library solution is even possible with how many complexities there are with all kinds of variadic arguments and storage classes D has.
The answer is clear then ;) Compilers traits dont require a DIP (IIRC) so just go on and be smart when answering the review comments.
Sep 09
parent reply Basile B. <b2.temp gmx.com> writes:
On Thursday, 9 September 2021 at 12:48:03 UTC, Basile B. wrote:
 On Thursday, 9 September 2021 at 11:45:55 UTC, Dennis wrote:
 On Thursday, 9 September 2021 at 10:14:03 UTC, Basile B. wrote:
 That's a contemporary D question that often comes in 
 conversations: should "feature x" be a builtin or should 
 "feature x" be made using metaprog...

 Is this used often ? is the metaprog version slow ?
Add "Is the metaprog version robust?". The given example doesn't work with `test(T...)(T args)`, doesn't work with `scope` parameters, doesn't work with non-copyable `ref` parameters, etc. I know it's a proof of concept, but I'm not sure a seamless library solution is even possible with how many complexities there are with all kinds of variadic arguments and storage classes D has.
The answer is clear then ;) Compilers traits dont require a DIP (IIRC) so just go on and be smart when answering the review comments.
Compilers traits dont require a DIP (IIRC) so just go on **with a PR** and be smart when answering the review comments.
Sep 09
parent reply Alexandru Ermicioi <alexandru.ermicioi gmail.com> writes:
On Thursday, 9 September 2021 at 12:49:16 UTC, Basile B. wrote:
 Compilers traits dont require a DIP (IIRC) so just go on **with 
 a PR** and be
 smart when answering the review comments.
You can already get the parameter list of a function using is expression. Smth like: ``` is(func Params == _parameters) ``` But it is a bit buggy, since you have to play a bit with it, before you can even extract the values. Imho, it would be better to improve the is expression rather than adding a new trait if possible. Best regards, Alexandru.
Sep 09
parent Adam D Ruppe <destructionator gmail.com> writes:
On Thursday, 9 September 2021 at 13:49:55 UTC, Alexandru Ermicioi 
wrote:
 You can already get the parameter list of a function using is 
 expression.
parameters are not arguments.
 But it is a bit buggy, since you have to play a bit with it, 
 before you can even extract the values.
the is expression works perfectly fine, it is just a different thing. parameters are static information about the function's outside. arguments are dynamic data inside the function. You can get to arguments through parameters though like I mentioned in the link in the OP though. A reasonable implementation is this: --- public static import std.meta; template ARGS(alias a /* always pass the first argument to your function to this */) { string helper() { string code = "std.meta.AliasSeq!("; static if(is(typeof(__traits(parent, a)) Params == __parameters)) foreach(idx, param; Params) { if(idx) code ~= ", "; code ~= __traits(identifier, Params[idx .. idx + 1]); } else static assert(0); code ~= ")"; return code; } enum string ARGS = helper(); } --- And then you can use it like: --- import std.stdio; void foo(int a) { foreach(item; mixin(ARGS!(a))) writeln(item); // forwarding can be done like this too: foo("omg", mixin(ARGS!a)); } void foo(string a, int b) { foreach(item; mixin(ARGS!(a))) writeln(item); } void main() { foo(4); foo("omg", 55); } --- This implementation doesn't work on variadic templates but that's not so important since they are already a tuple. Still though, it just would be nicer if it just worked with a builtin.
Sep 09
prev sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Thursday, 9 September 2021 at 08:39:05 UTC, bauss wrote:
 Here is a working example:
That doesn't work with overloads, but yeah, it isn't too hard to get a 90% solution in a few lines of library code.
 But yeah it would be nice if we could have it built-in, which I 
 don't think has been done.
aye.
Sep 09
next sibling parent WebFreak001 <d.forum webfreak.org> writes:
On Thursday, 9 September 2021 at 14:37:04 UTC, Adam D Ruppe wrote:
 On Thursday, 9 September 2021 at 08:39:05 UTC, bauss wrote:
 But yeah it would be nice if we could have it built-in, which 
 I don't think has been done.
aye.
aye.
Sep 09
prev sibling parent reply Tejas <notrealemail gmail.com> writes:
On Thursday, 9 September 2021 at 14:37:04 UTC, Adam D Ruppe wrote:
 On Thursday, 9 September 2021 at 08:39:05 UTC, bauss wrote:
 Here is a working example:
That doesn't work with overloads, but yeah, it isn't too hard to get a 90% solution in a few lines of library code.
 But yeah it would be nice if we could have it built-in, which 
 I don't think has been done.
aye.
Think it would be nice to extend it so that we can get template arguments as well? If we're thinking if implementing this thing, might as well go the full way
Sep 09
parent Adam D Ruppe <destructionator gmail.com> writes:
On Thursday, 9 September 2021 at 15:43:42 UTC, Tejas wrote:
 Think it would be nice to extend it so that we can get template 
 arguments as well?
well those would have to be separate, but yeah, i'd be ok with a template argument as well. less useful to me in general but a harmless add at least.
Sep 09
prev sibling next sibling parent reply Dukc <ajieskola gmail.com> writes:
On Wednesday, 8 September 2021 at 21:53:21 UTC, Per Nordlöw wrote:
 Adam, and like others including me, are longing for a 
 trait/builtin [1] that returns the parameters passed to the 
 function of the current scope (if any). Has such a thing been 
 proposed previously?

 [1] 
 http://dpldocs.info/this-week-in-d/Blog.Posted_2021_07_26.html#on-my-wish-list
Why it should be a built-in? Apart from that requirement, `Parameters!(mixin(__FUNCTION__))` does the trick. A bit verbose but not much more so than the `__traits(...)` built-ins.
Sep 09
next sibling parent Dukc <ajieskola gmail.com> writes:
On Thursday, 9 September 2021 at 09:22:35 UTC, Dukc wrote:
 Why it should be a built-in? Apart from that requirement,
 `Parameters!(mixin(__FUNCTION__))` does the trick. A bit 
 verbose but not much more so than the `__traits(...)` built-ins.
Oh sorry, I see you meant an alias sequence to the parameters directly, not just their types. My bad.
Sep 09
prev sibling parent reply bauss <jj_1337 live.dk> writes:
On Thursday, 9 September 2021 at 09:22:35 UTC, Dukc wrote:
 On Wednesday, 8 September 2021 at 21:53:21 UTC, Per Nordlöw 
 wrote:
 Adam, and like others including me, are longing for a 
 trait/builtin [1] that returns the parameters passed to the 
 function of the current scope (if any). Has such a thing been 
 proposed previously?

 [1] 
 http://dpldocs.info/this-week-in-d/Blog.Posted_2021_07_26.html#on-my-wish-list
Why it should be a built-in? Apart from that requirement, `Parameters!(mixin(__FUNCTION__))` does the trick. A bit verbose but not much more so than the `__traits(...)` built-ins.
That doesn't do the same thing. Parameters returns the type of each parameter. __arguments in the case of OP holds the value of each parameter. ```d Parameters!(mixin(__FUNCTION__)) ``` Ex. for a function like: ```d void a(int x, int y); ``` It'll actually give you: ```d (int, int) ``` When really OP wants: ```d [x, y] ```
Sep 09
parent bauss <jj_1337 live.dk> writes:
On Thursday, 9 September 2021 at 09:28:17 UTC, bauss wrote:
 On Thursday, 9 September 2021 at 09:22:35 UTC, Dukc wrote:
 On Wednesday, 8 September 2021 at 21:53:21 UTC, Per Nordlöw 
 wrote:
 Adam, and like others including me, are longing for a 
 trait/builtin [1] that returns the parameters passed to the 
 function of the current scope (if any). Has such a thing been 
 proposed previously?

 [1] 
 http://dpldocs.info/this-week-in-d/Blog.Posted_2021_07_26.html#on-my-wish-list
Why it should be a built-in? Apart from that requirement, `Parameters!(mixin(__FUNCTION__))` does the trick. A bit verbose but not much more so than the `__traits(...)` built-ins.
That doesn't do the same thing. Parameters returns the type of each parameter. __arguments in the case of OP holds the value of each parameter. ```d Parameters!(mixin(__FUNCTION__)) ``` Ex. for a function like: ```d void a(int x, int y); ``` It'll actually give you: ```d (int, int) ``` When really OP wants: ```d [x, y] ```
The problem with ParameterIdentifierTuple which would give you the identifiers is that you get string representations of them, so you have to use them in a way like I did in my example above. Because: ```d ParameterIdentifierTuple!(mixin(__FUNCTION__)) ``` Gives you: ```d tuple("x", "y") ```
Sep 09
prev sibling parent reply max haughton <maxhaton gmail.com> writes:
On Wednesday, 8 September 2021 at 21:53:21 UTC, Per Nordlöw wrote:
 Adam, and like others including me, are longing for a 
 trait/builtin [1] that returns the parameters passed to the 
 function of the current scope (if any). Has such a thing been 
 proposed previously?

 [1] 
 http://dpldocs.info/this-week-in-d/Blog.Posted_2021_07_26.html#on-my-wish-list
Implemented https://github.com/dlang/dmd/pull/13071
Sep 13
parent bauss <jj_1337 live.dk> writes:
On Monday, 13 September 2021 at 11:43:10 UTC, max haughton wrote:
 On Wednesday, 8 September 2021 at 21:53:21 UTC, Per Nordlöw 
 wrote:
 Adam, and like others including me, are longing for a 
 trait/builtin [1] that returns the parameters passed to the 
 function of the current scope (if any). Has such a thing been 
 proposed previously?

 [1] 
 http://dpldocs.info/this-week-in-d/Blog.Posted_2021_07_26.html#on-my-wish-list
Implemented https://github.com/dlang/dmd/pull/13071
That is beautiful. It looks so much better with compiler support!
Sep 13