Thread overview
Idea: extend typesafe variadic functions
Apr 01, 2007
Daniel Keep
Apr 01, 2007
Davidl
Apr 01, 2007
Davidl
April 01, 2007
One of the "cool features you probably didn't know about" with typesafe variadic functions is that you can make a variadic class parameter which will be constructed with the parameters to the function, like so:

class A
{
    this(int x, float y){}
}

void func(A a...)
{

}

...

func(3, 4.5);

This will implicitly call the constructor for A when you call func() and will forward those parameters to the class constructor.

What would be really cool is to have this happen for an array of classes or structs as well:

class A
{
    this(int x) {}
    this(float x) {}
    this(char[] s) {}
}

void func(A[] args...)
{

}

...

func(1, 2.3, "hi");

Right now, it says "cannot implicitly convert 1 to A" or something, but with this new feature, this would construct three instances of A, one using the int constructor, one using the float, and one using the string.  Of course, for sanity's sake, it would only try to construct As using single-parameter constructors.

This would work similarly for structs:

struct S
{
    static S opCall(T)(T value)
    {
        S s;
        return s;
    }
}

void func(S[] args...)
{

}

...

func(1, 2.3, "hi");

(See if you can figure out why I think this would be cool.. ;) )


April 01, 2007

Jarrett Billingsley wrote:
> One of the "cool features you probably didn't know about" with typesafe variadic functions is that you can make a variadic class parameter which will be constructed with the parameters to the function, like so:
> 
> class A
> {
>     this(int x, float y){}
> }
> 
> void func(A a...)
> {
> 
> }
> 
> ....
> 
> func(3, 4.5);
> 
> This will implicitly call the constructor for A when you call func() and will forward those parameters to the class constructor.

*Boggle*  When did *that* happen?!

> What would be really cool is to have this happen for an array of classes or structs as well:
> 
> class A
> {
>     this(int x) {}
>     this(float x) {}
>     this(char[] s) {}
> }
> 
> void func(A[] args...)
> {
> 
> }
> 
> ....
> 
> func(1, 2.3, "hi");
> 
> Right now, it says "cannot implicitly convert 1 to A" or something, but with this new feature, this would construct three instances of A, one using the int constructor, one using the float, and one using the string.  Of course, for sanity's sake, it would only try to construct As using single-parameter constructors.
> 
> This would work similarly for structs:
> 
> struct S
> {
>     static S opCall(T)(T value)
>     {
>         S s;
>         return s;
>     }
> }
> 
> void func(S[] args...)
> {
> 
> }
> 
> ....
> 
> func(1, 2.3, "hi");
> 
> (See if you can figure out why I think this would be cool.. ;) )

I'm afraid I can't :(

I imagine that there's probably some very nice things you could do with this, but I can't see why you couldn't do it already:

void funcT(Ts...)(Ts args)
{
    A[] as;
    as.length = args.length;
    foreach( i, arg ; args )
        as[i] = new A(arg);

    func(as);
}

Getting this to work with overloads would be... interesting, but certainly doable.  Heck, you could probably turn the above into a generic templated "array-of-T" initializer.

On a side note, am I the only one who is *really* uncomfortable with the fact that the first example works at all?  :S

	-- Daniel

-- 
int getRandomNumber()
{
    return 4; // chosen by fair dice roll.
              // guaranteed to be random.
}

http://xkcd.com/

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
April 01, 2007
since the feature is somewhat vialoating the type safe checking, i think restriction
may be required in case of misusing of this feature like:
1. class must have more than 1 ctor, and they must all accept only 1 argument
2. the func using class A as the variadic arg must only envolve the use of A, no other type could be accepted as other args
3. a hint when calling the func might be appreciated?
4. maybe the class ctor must be declare of this type like :
class A
{
	super this (int x)
        {}
}

And in my opinion, it's a great solution to the tango IO calling evaluation problem , and i think it's quite useful for mangle to provide user a great experience of calling Stdout. Coz i dislike the ("adkfj").(343).("akdsfj") too much :(
And I hope Kris, Lars, Sean could forgive me of that ;)

> One of the "cool features you probably didn't know about" with typesafe
> variadic functions is that you can make a variadic class parameter which
> will be constructed with the parameters to the function, like so:
>
> class A
> {
>     this(int x, float y){}
> }
>
> void func(A a...)
> {
>
> }
>
> ...
>
> func(3, 4.5);
>
> This will implicitly call the constructor for A when you call func() and
> will forward those parameters to the class constructor.
>
> What would be really cool is to have this happen for an array of classes or
> structs as well:
>
> class A
> {
>     this(int x) {}
>     this(float x) {}
>     this(char[] s) {}
> }
>
> void func(A[] args...)
> {
>
> }
>
> ...
>
> func(1, 2.3, "hi");
>
> Right now, it says "cannot implicitly convert 1 to A" or something, but with
> this new feature, this would construct three instances of A, one using the
> int constructor, one using the float, and one using the string.  Of course,
> for sanity's sake, it would only try to construct As using single-parameter
> constructors.
>
> This would work similarly for structs:
>
> struct S
> {
>     static S opCall(T)(T value)
>     {
>         S s;
>         return s;
>     }
> }
>
> void func(S[] args...)
> {
>
> }
>
> ...
>
> func(1, 2.3, "hi");
>
> (See if you can figure out why I think this would be cool.. ;) )
>
>

April 01, 2007
I haven't noticed what u have said. great point. the implementation of func(A[] ...) would need some templates, if not we would come to the problem of what tango comes to.
April 01, 2007
"Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:eundlt$sl7$1@digitalmars.com...
> I'm afraid I can't :(
>
> I imagine that there's probably some very nice things you could do with this, but I can't see why you couldn't do it already:
>
> void funcT(Ts...)(Ts args)
> {
>    A[] as;
>    as.length = args.length;
>    foreach( i, arg ; args )
>        as[i] = new A(arg);
>
>    func(as);
> }

You got it!  See, if we could do this, this would allow these kind of functions to be non-templated, meaning far less code bloat, the ability to overload, and the ability to override in classes, but with almost the same amount of expressiveness.  People writing scripting language binding libraries might find it _very_ useful..

> Getting this to work with overloads would be... interesting, but certainly doable.  Heck, you could probably turn the above into a generic templated "array-of-T" initializer.

I was thinking about that.  But then you've still got the code bloat issues..

> On a side note, am I the only one who is *really* uncomfortable with the fact that the first example works at all?  :S

I think it's pretty cool, though I can see why you're kind of wary of it. Most of the rest of the language doesn't use implicit conversions.