Jump to page: 1 2
Thread overview
Obtaining argument names in (variadic) functions
Mar 16, 2016
data pulverizer
Mar 16, 2016
jkpl
Mar 16, 2016
JR
Mar 16, 2016
data pulverizer
Mar 16, 2016
JR
Mar 16, 2016
data pulverizer
Mar 17, 2016
Edwin van Leeuwen
Mar 17, 2016
JR
Mar 17, 2016
Edwin van Leeuwen
Mar 20, 2016
JR
March 16, 2016
Hi D gurus,

is there a way to obtain parameter names within the function body? I am particularly interested in variadic functions. Something like:

void myfun(T...)(T x){
    foreach(i, arg; x)
        writeln(i, " : ", arg);
}

void main(){
    myfun(a = 2, b = "two", c = 2.0);
}

// should print
a : 2
b : two
c : 2.0

Thanks in advance

Loving the mixins and tuples
March 16, 2016
On 3/16/16 4:24 PM, data pulverizer wrote:
> Hi D gurus,
>
> is there a way to obtain parameter names within the function body? I am
> particularly interested in variadic functions. Something like:
>
> void myfun(T...)(T x){
>      foreach(i, arg; x)
>          writeln(i, " : ", arg);
> }
>
> void main(){
>      myfun(a = 2, b = "two", c = 2.0);
> }

This isn't valid code. The name of the parameters is x[0], x[1], and x[2].

You could do something like:

myfun("a", 2, "b", "two", "c", 2.0);

and process it properly.

-Steve
March 16, 2016
On Wednesday, 16 March 2016 at 20:24:38 UTC, data pulverizer wrote:
> Hi D gurus,
>
> is there a way to obtain parameter names within the function body? I am particularly interested in variadic functions. Something like:
>
> void myfun(T...)(T x){
>     foreach(i, arg; x)
>         writeln(i, " : ", arg);
> }
>
> void main(){
>     myfun(a = 2, b = "two", c = 2.0);
> }
>
> // should print
> a : 2
> b : two
> c : 2.0
>
> Thanks in advance
>
> Loving the mixins and tuples

I try to anticipate the reason why you want this. As said in a previous answer you can access to an individual element by using the array syntax but also _param_<X>, with X the index of the parameter:

void myfun(T...)(T x)
{
    import std.traits; import std.stdio;
    writeln(ParameterIdentifierTuple!(myfun!T));
    writeln(_param_0);
    writeln(_param_1);
    writeln(_param_2);
}

void main()
{
    int a=1,b=2,c=3;
    myfun(a,b,c);
}
March 16, 2016
On Wednesday, 16 March 2016 at 20:24:38 UTC, data pulverizer wrote:
> Hi D gurus,
>
> is there a way to obtain parameter names within the function body? I am particularly interested in variadic functions. Something like:
>
> void myfun(T...)(T x){
>     foreach(i, arg; x)
>         writeln(i, " : ", arg);
> }
>
> void main(){
>     myfun(a = 2, b = "two", c = 2.0);
> }
>
> // should print
> a : 2
> b : two
> c : 2.0
>
> Thanks in advance
>
> Loving the mixins and tuples

You can do it precisely like that if the variables/symbols you pass as (template) arguments are properly declared first.

http://dpaste.dzfl.pl/0b452efeaaab


void printVars(Args...)()
if (Args.length > 0)
{
    import std.stdio : writefln;

    foreach (i, arg; Args) {
        writefln("%s\t%s:\t%s", typeof(Args[i]).stringof, Args[i].stringof, arg);
    }
}

void main() {
    int abc = 3;
    string def = "58";
    float ghi = 3.14f;
    double jkl = 3.14;

    printVars!(abc,def,ghi,jkl)();
}
March 16, 2016
On Wednesday, 16 March 2016 at 20:53:42 UTC, JR wrote:
> On Wednesday, 16 March 2016 at 20:24:38 UTC, data pulverizer wrote:
>> Hi D gurus,
>>
>> is there a way to obtain parameter names within the function body? I am particularly interested in variadic functions. Something like:
>>
>> void myfun(T...)(T x){
>>     foreach(i, arg; x)
>>         writeln(i, " : ", arg);
>> }
>>
>> void main(){
>>     myfun(a = 2, b = "two", c = 2.0);
>> }
>>
>> // should print
>> a : 2
>> b : two
>> c : 2.0
>>
>> Thanks in advance
>>
>> Loving the mixins and tuples
>
> You can do it precisely like that if the variables/symbols you pass as (template) arguments are properly declared first.
>
> http://dpaste.dzfl.pl/0b452efeaaab
>
>
> void printVars(Args...)()
> if (Args.length > 0)
> {
>     import std.stdio : writefln;
>
>     foreach (i, arg; Args) {
>         writefln("%s\t%s:\t%s", typeof(Args[i]).stringof, Args[i].stringof, arg);
>     }
> }
>
> void main() {
>     int abc = 3;
>     string def = "58";
>     float ghi = 3.14f;
>     double jkl = 3.14;
>
>     printVars!(abc,def,ghi,jkl)();
> }

That's brilliant! Thanks JR
March 16, 2016
On Wednesday, 16 March 2016 at 20:43:09 UTC, jkpl wrote:
> I try to anticipate the reason why you want this. [...]

I use something *kinda* sort of similar in my toy project to print all fields of a struct, for debugging purposes when stuff goes wrong. Getting the names of the member variables is crucial then.

http://dpaste.dzfl.pl/748c4dd97de6
March 16, 2016
On Wednesday, 16 March 2016 at 21:05:43 UTC, JR wrote:
> On Wednesday, 16 March 2016 at 20:43:09 UTC, jkpl wrote:
>> I try to anticipate the reason why you want this. [...]
>
> I use something *kinda* sort of similar in my toy project to print all fields of a struct, for debugging purposes when stuff goes wrong. Getting the names of the member variables is crucial then.
>
> http://dpaste.dzfl.pl/748c4dd97de6

That's a nice learning piece. I think "with" is cool, reminds me of a nice R feature.
March 17, 2016
On Wednesday, 16 March 2016 at 20:53:42 UTC, JR wrote:
>
>
> void printVars(Args...)()
> if (Args.length > 0)
> {
>     import std.stdio : writefln;
>
>     foreach (i, arg; Args) {
>         writefln("%s\t%s:\t%s", typeof(Args[i]).stringof, Args[i].stringof, arg);
>     }
> }
>
> void main() {
>     int abc = 3;
>     string def = "58";
>     float ghi = 3.14f;
>     double jkl = 3.14;
>
>     printVars!(abc,def,ghi,jkl)();
> }

Interesting, any idea if it is possible to do assignment within template.. Either:

printVars!(int abc=5,string def="58")();
or something like
printVars!("abc","def",ghi)(5,"58");

March 17, 2016
On Thursday, 17 March 2016 at 11:52:13 UTC, Edwin van Leeuwen wrote:
> On Wednesday, 16 March 2016 at 20:53:42 UTC, JR wrote:
>>
>>
>> void printVars(Args...)()
>> if (Args.length > 0)
>> {
>>     import std.stdio : writefln;
>>
>>     foreach (i, arg; Args) {
>>         writefln("%s\t%s:\t%s", typeof(Args[i]).stringof, Args[i].stringof, arg);
>>     }
>> }
>>
>> void main() {
>>     int abc = 3;
>>     string def = "58";
>>     float ghi = 3.14f;
>>     double jkl = 3.14;
>>
>>     printVars!(abc,def,ghi,jkl)();
>> }
>
> Interesting, any idea if it is possible to do assignment within template.. Either:
>
> printVars!(int abc=5,string def="58")();
> or something like
> printVars!("abc","def",ghi)(5,"58");

What would the use-cases for those be?

I don't think the first is valid grammar, and I'm not sure what you want the second to do. Resolve symbols by string literals of their names? That might need a string mixin as they wouldn't be in scope when in the called template function, but I've never tried it.

You *can* cook up something that modifies the values of variables you pass in -- like modifyVars!(abc,def,ghi)("asdf", 123, 3.14) -- but you just might be better off with runtime ref parameters then.
March 17, 2016
On Thursday, 17 March 2016 at 13:53:00 UTC, JR wrote:
>>
>> Interesting, any idea if it is possible to do assignment within template.. Either:
>>
>> printVars!(int abc=5,string def="58")();
>> or something like
>> printVars!("abc","def",ghi)(5,"58");
>
> What would the use-cases for those be?
>
> I don't think the first is valid grammar, and I'm not sure what you want the second to do. Resolve symbols by string literals of their names? That might need a string mixin as they wouldn't be in scope when in the called template function, but I've never tried it.

Both use cases are when you want a named parameter, without having to assign it first. I know the first is not valid grammar, was just wondering if you might be smarter than me and see a way to make it valid :)

Second one is another possible alternative that I have been thinking about.

Basically, say I want to have the named (optional) parameters x and y. In your initial example I would be required to do:

```
int x = 1;
string y = "2";
doSomethingWithNamedPars!(x,y)();
```

I just hoped to shorten that to a one liner similar to:

```
doSomethingWithNamedPars!(x=1,y="2")();
```

or alternatively

```
doSomethingWithNamedPars!("x","y")(1,"2");
```

(where doSomethingWithNamedPars's behaviour depends on which named parameters it is passed)

Just as a reference, my current approach (in ggplotd) is with named tuples, but that is slightly more verbose than I had hoped:

```
doSomethingWithNamedPars( Tuple!(int, "x", string, "y")( 1, 2 ) );
```
« First   ‹ Prev
1 2