Applying a tuple to a function (and more)

Philippe Sigaud philippe.sigaud at gmail.com
Sat Sep 18 12:44:56 PDT 2010


On Sat, Sep 18, 2010 at 19:59, Juanjo Alvarez <juanjux at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-learn/attachments/20100918/5652ecc6/attachment.html>


More information about the Digitalmars-d-learn mailing list