Thread overview | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 07, 2012 How to create TypeTuple/ExpressionTuple from tuple/tuples | ||||
---|---|---|---|---|
| ||||
Given e.g. a function template void f(T ...)(T t) { writeln(t.length); } How can I call this function with an already-constructed tuple but pass the pule as an expressiontuple? auto v = tuple(1, 2, 3); f(v); In the case above, f will print 1 because 1 tuple is given to the function, but I want to 'flatten' the tuple before the call, making the function see all the values in the tuple and thus print 3. I cannot change the function. Similarly, I want to be able to do this: auto v0 = tuple(1, 2, 3); auto v1 = tuple(4, 5, 6); f(some_function_to_combine_and_flatten_tuples(v0, v1)); And have f print 6.. Calling f(v0, v1) will print 2. One reason for needing this is that I am using the receive function in std.concurrency, and I want to be able to merge message handlers from multiple locations. |
August 07, 2012 Re: How to create TypeTuple/ExpressionTuple from tuple/tuples | ||||
---|---|---|---|---|
| ||||
Posted in reply to Øivind | On 8/7/12, "Øivind" <oivind.loe@gmail.com> wrote:
> How can I call this function with an already-constructed tuple but pass the pule as an expressiontuple?
>
> auto v = tuple(1, 2, 3);
> f(v);
Use the .expand property:
f(v.expand)
|
August 07, 2012 Re: How to create TypeTuple/ExpressionTuple from tuple/tuples | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On Tuesday, 7 August 2012 at 16:11:05 UTC, Andrej Mitrovic wrote:
> On 8/7/12, "Øivind" <oivind.loe@gmail.com> wrote:
>> How can I call this function with an already-constructed tuple
>> but pass the pule as an expressiontuple?
>>
>> auto v = tuple(1, 2, 3);
>> f(v);
>
> Use the .expand property:
> f(v.expand)
Works like a charm. Thanks!
The last one then becomes f(v0.expand, v1.expand)
|
August 07, 2012 Re: How to create TypeTuple/ExpressionTuple from tuple/tuples | ||||
---|---|---|---|---|
| ||||
Posted in reply to Øivind | On 8/7/12, "Øivind" <oivind.loe@gmail.com> wrote:
> The last one then becomes f(v0.expand, v1.expand)
Yeah. It's somewhat possible to use a helper function for multiple TypeTuples, but the problem is D functions cannot return language tuples (only TypeTuple from std.typecons which is what the tuple() call creates) so you would always need to call "expand" before the function call, e.g.:
void f(T...)(T t)
{
writeln(t.length);
}
auto expand(T...)(T t)
{
static if (T.length == 1)
{
return t[0];
}
else
static if (T.length > 1)
{
return tuple(t[0].expand, expand(t[1..$]).expand);
}
}
void main()
{
auto v0 = tuple(1, 2, 3);
auto v1 = tuple(4, 5, 6);
auto v2 = tuple(7, 8, 9);
f(expand(v0, v1, v2).expand);
}
Once D is improved enough to be able to return language tuples this should be easier to use.
|
August 07, 2012 Re: How to create TypeTuple/ExpressionTuple from tuple/tuples | ||||
---|---|---|---|---|
| ||||
On Tue, Aug 7, 2012 at 7:35 PM, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote: > Yeah. It's somewhat possible to use a helper function for multiple TypeTuples, but the problem is D functions cannot return language tuples (only TypeTuple from std.typecons which is what the tuple() call creates) so you would always need to call "expand" before the function call, e.g.: You can also take the 'dual' of your solution and have a template that makes a function automatically expand tuples: alias expander!foo efoo; // efoo is a function that accepts tuples and automatically cracks them open for you, and then pass them to foo auto result = efoo(tuple(1,2), "abc", tuple('a', 3.14)); assert(result = foo(1,2,"abc", 'a', 3.14)); The same idea could be use to have a function 'expand' any user-defined type, be they structs or classes, by applying .tupleof on them. The code for expander is a little bit involved, I'm afraid, I had to use a helper struct. import std.traits; import std.typecons; struct Fill(Expanded...) { Expanded expanded; void from(int index = 0, TupleOrNot...)(TupleOrNot args) { static if (TupleOrNot.length > 0) { static if (isTuple!(TupleOrNot[0])) // It's a tuple, expand it ... { expanded[index..index+TupleOrNot[0].length] = args[0].expand; from!(index+TupleOrNot[0].length)(args[1..$]); // ... and continue the recursion } else // it's not a tuple, let it that way... { expanded[index] = args[0]; from!(index+1)(args[1..$]); // ...and continue the recursion } } } } /** Take a function fun and return a transformed function that will expand std.typecons.Tuple's provided as arguments and let other args untouched */ template expander(alias fun) if (isSomeFunction!fun) { ReturnType!fun expander(Args...)(Args args) { Fill!(ParameterTypeTuple!fun) f; // prepare the future arguments f.from(args); // does the expansion job, the arguments are stored in f.expanded return fun(f.expanded); } } void main() { int foo(int i, double d, string s, char c) { return i + cast(int)d + s.length + (c - '0');} alias expander!foo efoo; writeln( foo(1, 3.14, "abc", 'a') ); writeln( efoo(tuple(1, 3.14, "abc", 'a')) ); writeln( efoo(tuple(1, 3.14), "abc", 'a') ); writeln( efoo(tuple(1, 3.14), tuple("abc", 'a')) ); } |
August 07, 2012 Re: How to create TypeTuple/ExpressionTuple from tuple/tuples | ||||
---|---|---|---|---|
| ||||
On 8/7/12, Philippe Sigaud <philippe.sigaud@gmail.com> wrote:
> You can also take the 'dual' of your solution and have a template that makes a function automatically expand tuples
But that doesn't work for variadic templates, which is the OP's case:
int foo(T...)(T t) { return 1; }
alias expander!foo efoo; // error
|
August 08, 2012 Re: How to create TypeTuple/ExpressionTuple from tuple/tuples | ||||
---|---|---|---|---|
| ||||
On Tue, Aug 7, 2012 at 11:31 PM, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> On 8/7/12, Philippe Sigaud <philippe.sigaud@gmail.com> wrote:
>> You can also take the 'dual' of your solution and have a template that makes a function automatically expand tuples
>
> But that doesn't work for variadic templates, which is the OP's case:
>
> int foo(T...)(T t) { return 1; }
> alias expander!foo efoo; // error
The template can easily be modified to deal with template functions, but in that case, you lose the parameter-type verification, for example if the function template has a constraint.
|
August 08, 2012 Re: How to create TypeTuple/ExpressionTuple from tuple/tuples | ||||
---|---|---|---|---|
| ||||
On Wed, Aug 8, 2012 at 7:01 AM, Philippe Sigaud <philippe.sigaud@gmail.com> wrote: >> But that doesn't work for variadic templates, which is the OP's case: >> >> int foo(T...)(T t) { return 1; } >> alias expander!foo efoo; // error > > The template can easily be modified to deal with template functions, but in that case, you lose the parameter-type verification, for example if the function template has a constraint. Like this: /// Helper template to flatten a Tuple template Expand(T) { static if (isTuple!T) alias T.Types Expand; else alias T Expand; } /** Take a function fun and return a transformed function that will expand std.typecons.Tuple's provided as arguments and let other args untouched */ template expander(alias fun) { auto expander(Args...)(Args args) { static if (isSomeFunction!fun) alias ParameterTypeTuple!fun Expanded; else alias staticMap!(Expand, Args) Expanded; // flatten the tuples Expanded expanded; /// Does the filling work: put values extracted from t in expanded void from(int index = 0, TupleOrNot...)(TupleOrNot t) { static if (TupleOrNot.length > 0) { static if (isTuple!(TupleOrNot[0])) // It's a tuple, expand it ... { expanded[index..index+TupleOrNot[0].length] = t[0].expand; from!(index+TupleOrNot[0].length)(t[1..$]); } else // it's not a tuple, let it that way... { expanded[index] = t[0]; from!(index+1)(t[1..$]); // ...and continue the recursion } } } from(args); return fun(expanded); } } int foo(Ts...)(Ts ts) { return Ts.length; } void main() { alias expander!foo efoo; writeln( foo(1, 3.14, "abc", 'a') ); // 4 writeln( efoo(tuple(1, 3.14, "abc", 'a')) ); // 4 writeln( efoo(tuple(1, 3.14), "abc", 'a') ); // 4 writeln( efoo(tuple(1, 3.14), tuple("abc", 'a')) ); // 4 } |
August 08, 2012 Re: How to create TypeTuple/ExpressionTuple from tuple/tuples | ||||
---|---|---|---|---|
| ||||
On 8/8/12, Philippe Sigaud <philippe.sigaud@gmail.com> wrote:
> Like this..
That's really cool. Could you put this in the DT book, along with your previous sample? Good job btw!
|
August 08, 2012 Re: How to create TypeTuple/ExpressionTuple from tuple/tuples | ||||
---|---|---|---|---|
| ||||
On Wed, Aug 8, 2012 at 7:19 PM, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> On 8/8/12, Philippe Sigaud <philippe.sigaud@gmail.com> wrote:
>> Like this..
>
> That's really cool. Could you put this in the DT book, along with your previous sample? Good job btw!
Thanks.
Hey, every time I do something like that, you ask me to put it in my
template tutorial ;)
I'm not sure it's *so* useful. Maybe a generic destructuring template,
that opens structs, classes, arrays?
|
Copyright © 1999-2021 by the D Language Foundation