Variadic grouping

JS js.mdnq at gmail.com
Sat Aug 10 19:07:31 PDT 2013


On Saturday, 10 August 2013 at 18:28:39 UTC, Artur Skawina wrote:
> On 08/10/13 12:19, John Colvin wrote:
>> On Monday, 29 July 2013 at 13:23:23 UTC, JS wrote:
>>> Sometimes it's nice to be able to have groups of variadic 
>>> parameters:
>>>
>>> template t(T1..., T2...)
>>>
>>> ...
>>>
>>> t!(a, b, c; d, e, f);
>>>
>>> so that a,b,c are for T1 and d,e,f are for T2.
>>>
>>> This can be done by making a symbol and breaking up a single 
>>> variadic but is messy.
>>>
>>> I doubt such a feature will ever get added but who knows...
>> 
>> I was initially unimpressed, but after some recent work I 
>> would really like this feature. I have been using
>>   struct Group(T...)
>>   {
>>       alias Ungroup = T;
>>   }
>> but, useful as it is, this feels like something that should 
>> have some sugar on it.
>> 
>>   template A(T0 ..., T1 ...)
>>   {
>>   // use T0 & T1
>>   }
>> 
>>   A!(int, long, double; Point, int)
>> 
>> is so much nicer than
>> 
>>   template A(T0, T1)
>>   if(isGroup!T0 && isGroup!T1)
>>   {
>>       alias t0 = T0.Ungroup;
>>       alias t1 = T1.Ungroup;
>> 
>>       //use t0 && t1
>>   }
>> 
>>   A!(Group!(int, long, double), Group!(Point, int))
>
>    template Tuple(A...) { alias Tuple = A; }
>
>    template Ungroup(G...) if (G.length==1) {
>       static if(__traits(compiles, Tuple!(G[0].Ungroup)))
>          alias Ungroup = Tuple!(G[0].Ungroup);
>       else
>          alias Ungroup = Tuple!(G[0]);
>    }
>
> then
>
>    template A(T...) {
>       //alias t0 = Ungroup!(T[0]);
>       //alias t1 = Ungroup!(T[1]);
> 
>       //use t0 && t1
>
>       static assert( {
>          foreach (ET; T)
>             pragma(msg, Ungroup!ET);
>          return 1;
>       }());
> 
>       alias A = Ungroup!(T[0])[0];
>       Ungroup!(T[2])[$-1] AFloat;
>    }
>
>    A!(Group!(int, long, double), Group!(Point, int), float) x;
>    A!(int, Group!(Point, int), Group!("f", float)) x2;
>    A!(int, Group!(Point, int), float, "blah", double, 
> Group!(ubyte, "m", float[8], 3.14)) x3;
>    A!(int, 0, float, Group!(ubyte, "m", float[2], 
> Group!(Group!(int,11,12), Group!(float,21,22)))) x4;
>
>
> Using just ';' would: a) be too subtle and confusing; b) not be 
> enough
> to handle the 'x4' case above.
>
> artur

a) thats your opinion.

b) wrong. Using Group is just an monstrous abuse of syntax. It's 
not needed. I don't think there is a great need for nested 
groupings, but if so it is easy to make ';' work.

Do your really think

that Group!() is any different than `;` as far as logic goes? If 
so then you really need to learn to think abstractly.

This is like saying that there is a difference between using () 
or {} as groupings. There is no semantic difference except what 
you choose to put on it. Hell we could use ab for grouping 
symbols.

Group!() and (); are the same except one is shorter and IMO more 
convienent... there is otherwise, no other difference.

to see this, x4 can be written as


A!(int, 0, float, (ubyte, "m", float[2], ((int,11,12), 
(float,21,22)))) x4;

Note, all I did was delete Group!. IT IS HAS THE EXACT SAME 
LOGICAL INTERPRETATION. Just because it is more confusing for you 
does mean anything except you need to try harder.

In this case, there is no need to use `;` because there is no 
group separation(in your definition of A). I would prefer to 
write it as

A!(int, 0, float, (ubyte, "m", float[2], (int,11,12; 
float,21,22))) x4;

As I can see the groups easier. In this case the ; serves only to 
distinguish linear groupings, not nested ones as it can't do 
this... brackets must be used.


Linear groupings(sequential groups) are what is going to be used 
most of the time. I did not not have the need for nesting groups 
so didn't use brackets but it would be something needed for some. 
I don't think there would be a huge reason to have nested 
groupings since it is generally a compile time construct but I 
suppose in some instances it could be useful. e.g., key value 
pairs: ((k1, v1), (k2, v2), ...) but even then one could just 
write it (k1, v1; k2, v2; ....)

The main point is that what you are trying to offer does not 
simplify things... and simplification is what is important. D can 
already do what is required in a roundabout way but it requires 
extra work and is more verbose(which I think, in general, is bad).

I'd rather have something like # instead of group. e.g.,


Just because you add some symbol in front of brackets does not 
magically make anything you do different... just extra typing.


>    A!(int, 0, float, #(ubyte, "m", float[2], #(#(int,11,12), 
> #(float,21,22)))) x4;


But there should be no need for # as there is no need for Group. 
(again, I'm not talking about what D can do but what D should do)


More information about the Digitalmars-d mailing list