View mode: basic / threaded / horizontal-split · Log in · Help
January 05, 2010
Are named variadic arguments possible?
Is it possible, using templates, tuples, or some other mechanism, to implement named variadic arguments in D?

For example, I'd like to be able to do something like...
foo( 2, &bar, age : 10, status : "down");

and so forth.
January 05, 2010
Re: Are named variadic arguments possible?
Alex Wrote:

> Is it possible, using templates, tuples, or some other mechanism, to implement named variadic arguments in D?

Do you need high performance for this code?
If not, what about using an associative array of Variant[string] as third argument? It's not a nice solution.

Bye,
bearophile
January 05, 2010
Re: Are named variadic arguments possible?
> Do you need high performance for this code?
> If not, what about using an associative array of Variant[string] as third argument? It's not a nice solution.

It's not a nice solution, but that's essentially what Python does in such situation:
def foo(x, y, **kwds):
 # here kwds is a dict of str:value

In D there are Typesafe Variadic Functions, you can use:
int sum(int[] ar ...) {
To define a function that takes an arbitrary number of ints or a dynamic array of ints (and maybe fixed sized array of int too).
Another (weird! never used) alternative usage of the Typesafe Variadic Functions is to build an object on the fly.

So that syntax may be extended to support:
void foo(Variant[string] kwds ...) {
}

I may show this silly idea in the main D newsgroup later today.

Bye,
bearophile
January 05, 2010
Re: Are named variadic arguments possible?
Alex wrote:
> Is it possible, using templates, tuples, or some other mechanism, to implement named variadic arguments in D?
> 
> For example, I'd like to be able to do something like...
> foo( 2, &bar, age : 10, status : "down");
> 
> and so forth.

Yes, with a small hack.

typedef int age_type;

age_type age(int i) { return cast(age_type) i; }

void foo(T...)(int i, Bar*, T t) {
 // Test T for age_type here.
}
January 06, 2010
Re: Are named variadic arguments possible?
On 1/5/10 08:50, Alex wrote:
> Is it possible, using templates, tuples, or some other mechanism, to implement named variadic arguments in D?
>
> For example, I'd like to be able to do something like...
> foo( 2,&bar, age : 10, status : "down");
>
> and so forth.

You can try and see if you can modify this to do what you want: 
http://tango.pastebin.com/m2ae0ea3e it's named arguments but not variadic.
January 06, 2010
Re: Are named variadic arguments possible?
downs wrote:
> Alex wrote:
>> Is it possible, using templates, tuples, or some other mechanism, to implement named variadic arguments in D?
>>
>> For example, I'd like to be able to do something like...
>> foo( 2, &bar, age : 10, status : "down");
>>
>> and so forth.
> 
> Yes, with a small hack.
> 
> typedef int age_type;
> 
> age_type age(int i) { return cast(age_type) i; }
> 
> void foo(T...)(int i, Bar*, T t) {
>   // Test T for age_type here.
> }


In D2 this won't be possible for much longer, since typedef is going 
away. But you can fake it:

  template Typedef(T, string name)
  {
      mixin("struct "~name~" { "~T.stringof~" x; alias x this; }");
  }

  mixin Typedef!(int, "age_type");
  age_type age(int i) { return age_type(i); }

If you're going to use it a lot, you can even automate it further:

  template NamedArg(T, string name)
  {
      mixin Typedef!(T, name~"_type");
      mixin(name~"_type "~name~"("~T.stringof~" t) {"
	~" return "~name~"_type(t); }");
  }

  mixin NamedArg!(int, "age");
  mixin NamedArg!(string, "status");

  foo(2, &bar, age(10), status("down"));

-Lars
January 06, 2010
Re: Are named variadic arguments possible?
Lars T. Kyllingstad wrote:
> downs wrote:
>> Alex wrote:
>>> Is it possible, using templates, tuples, or some other mechanism, to 
>>> implement named variadic arguments in D?
>>>
>>> For example, I'd like to be able to do something like...
>>> foo( 2, &bar, age : 10, status : "down");
>>>
>>> and so forth.
>>
>> Yes, with a small hack.
>>
>> typedef int age_type;
>>
>> age_type age(int i) { return cast(age_type) i; }
>>
>> void foo(T...)(int i, Bar*, T t) {
>>   // Test T for age_type here.
>> }
> 
> 
> In D2 this won't be possible for much longer, since typedef is going 
> away. But you can fake it:
> 
>   template Typedef(T, string name)
>   {
>       mixin("struct "~name~" { "~T.stringof~" x; alias x this; }");
>   }
> 
>   mixin Typedef!(int, "age_type");
>   age_type age(int i) { return age_type(i); }
> 
> If you're going to use it a lot, you can even automate it further:
> 
>   template NamedArg(T, string name)
>   {
>       mixin Typedef!(T, name~"_type");
>       mixin(name~"_type "~name~"("~T.stringof~" t) {"
>     ~" return "~name~"_type(t); }");
>   }
> 
>   mixin NamedArg!(int, "age");
>   mixin NamedArg!(string, "status");
> 
>   foo(2, &bar, age(10), status("down"));

Forget that last part. I just realised you don't need the helper 
functions.. :)

  mixin Typedef!(int, "age");
  mixin Typedef!(int, "status");

  foo(2, &bar, age(10), status(down)); // should work

-Lars
January 12, 2010
Re: Are named variadic arguments possible?
Sorry, I guess I wasn't clear.  What I want is to be able to do something like the following:

void foo(...) {
 variadic [char[]] args = get_named_args(_arguments);
 foreach (k,v; args) {
   writefln("%s : %s", k, v);
 }
}

foo( name("john"), age(30), dob("6/24/1980") );

and have it print
name : john
age : 30
dob: 6/24/1980
January 12, 2010
Re: Are named variadic arguments possible?
Alex wrote:
> Sorry, I guess I wasn't clear.  What I want is to be able to do something like the following:
> 
> void foo(...) {
>   variadic [char[]] args = get_named_args(_arguments);
>   foreach (k,v; args) {
>     writefln("%s : %s", k, v);
>   }
> }
> 
> foo( name("john"), age(30), dob("6/24/1980") );
> 
> and have it print
> name : john
> age : 30
> dob: 6/24/1980

Could opDispatch be useful in some way?

The following is nowhere clean. Additionally, VarArg.value must be some 
sort of 'any type' instead of 'string value' for int arguments like 30 
to work. Still... :)

// Worked with dmd 2.039
import std.stdio;

struct VarArg
{
    string key;
    string value;
}

struct VarArgGenerator
{
    VarArg opDispatch(string key, T)(T value)
    {
        return VarArg(key, value);
    }
}

VarArgGenerator arg;

void foo(VarArg[] args...)
{
    foreach (arg; args) {
        writefln("%s : %s", arg.key, arg.value);
    }
}

void main()
{
    foo(arg.name("john"),
        arg.age("30"),
        arg.dob("6/24/1980"));
}

Ali
Top | Discussion index | About this forum | D home