On Sat, Sep 18, 2010 at 19:59, Juanjo Alvarez <juanjux@gmail.com> wrote:
I wanted to ask how these would be done, because I can't find how to do it:

1. Having the strings, defined at compile time, "MyClass" and "mymethod",
how could I could I get to a delegate to MyClass.mymethod?

You can insert them in a piece of code as a string, and then mix it in:

enum string code = "auto deleg = &" ~ className ~ "." ~ methodName ~ ";";   // auto deleg = &MyClass.mymethod;
mixin(code); // created deleg, you're good to go.

 

2. Is there any way to apply a tuple to a function, expanding as arguments?

Like:

void f(int a, double b) {}
auto tup = tuple(42, 3.14);
f(<magic goes here with tup expanding as 42, 3.14>);


Use the .field or .expand alias, exposed by Tuple!() to get a direct access to the internal expression tuple.

f(tup.expand); // cracks tup open

Recently, bug 2800 was corrected and you can also directly access a tuple's fields by indexing:

double d = tup[1];  // or simply:     auto d = tup[1];

Before that, you had to do

double d = tup.field[1];

Recently, tuples also got a .length member. That's handy.
As for expanding tuples inside functions if you do that regularly, I suggest you use a function adaptor, like this:

template tuplify(alias fun) if (isCallable!fun)
{
    ReturnType!fun tuplify(Tuple!(ParameterTypeTuple!fun) tup)
    {
        return fun(tup.expand);
    }
}

Usage:

alias tuplify!f tf;
tf(tup);

tf is a function, like any other. It accepts a Tuple!(int,double), cracks it open and pass it to f.

I don't know if you need some explanation on how it works?
Here it is anyway: tuplify is a template, a parameterized piece of code. tuplify takes only one template parameter, by alias. This means you give it a name, any identifier in the current scope. You do not give it a type. That's what allows you to write tuplify!f.

Here the result of the template instantation is a function with the same name 'tuplify'. When a template exposes only one identifier with its own name, it's as if the code inside the template got instantiated right there.
So tuplify!f is a function. It could have been a function template, or any other D construct. I used "alias tuplify!f tf;" to be able to use tf as ... an alias (doh!) to tuplify!f. But I could also have used:

auto tf = &(tuplify!f);  // tuplify!f is a function, tf is a pointer to this function.

You can treat tf as any other D function : pass it around, give it as a argument to other templates or functions, etc.

The template constraint if(isCallable!fun) means tuplify can only be instantiated on callables (function, delegates, pointer to functions, structs or classes with opCall defined, etc). Note that tuplify works on _all_ callables! After all, the only property I use in the code is that f can be called with ().

isCallable lives here:
http://digitalmars.com/d/2.0/phobos/std_traits.html#isCallable

I use the ReturnType and ParameterTypeTuple templates to do a little compile-time introspection

You can find ReturnType and ParameterTypeTuple here:
http://digitalmars.com/d/2.0/phobos/std_traits.html#ReturnType

So the internally created function accepts a Tuple!(the types fun needs) as argument. I indicate to the compiler it will return what fun returns, but I could have used auto there instead.

Philippe