• JS (9/9) Jul 29 2013 Sometimes it's nice to be able to have groups of variadic
• bearophile (6/7) Jul 29 2013 It seems a cute idea, but why don't you show two or more very
• JS (29/36) Jul 29 2013 The usefulness should be obvious and I seriously doubt if someone
• bearophile (14/31) Jul 29 2013 It's not obvious for me :-) Explaining the "obvious" is sometimes
• bearophile (31/35) Jul 29 2013 A static ternary operator is sometimes handy, this is working
• JS (40/72) Jul 29 2013 Possibly because it doesn't exist? The problem is that when
• John Colvin (9/13) Jul 29 2013 There are a mind-boggling large number of things that are useful,
• monarch_dodra (38/51) Jul 29 2013 The need for "grouping variadics" creeps up every now and then,
• bearophile (23/24) Jul 29 2013 Time ago I asked for an improvement of Select:
• bearophile (30/31) Jul 29 2013 Is this brutal enough? :-)
• bearophile (8/22) Jul 29 2013 It works in simple cases and maybe it's worth changing in some
• monarch_dodra (25/56) Jul 29 2013 But it's still "Select!(true, a, b)" and not "Select!(true, 1,
• monarch_dodra (2/42) Jul 29 2013 Wait never mind my above post. Your approach works.
• monarch_dodra (5/6) Jul 29 2013 Except for this...
• Meta (4/8) Jul 29 2013 I think it's a feature that this doesn't work. As for variadic
• JS (16/27) Jul 29 2013 I'm not sure how named parameters would solve the original
• Meta (13/18) Jul 29 2013 Your original use case:
• JS (8/27) Jul 29 2013 I don't think that is very robust notation but if it is then it
• Meta (46/53) Jul 29 2013 I think using f(..., name = ...) is pretty obvious, and possibly
• Meta (30/38) Jul 29 2013 Actually, I think I misunderstood your meaning. You're right,
• Artur Skawina (8/31) Jul 29 2013 template Select(bool condition, T...) if (T.length == 2) {
• Artur Skawina (15/46) Jul 29 2013 Or even:
• Dicebot (8/14) Jul 30 2013 That is actually a TypeTuple that does not auto-expand. May be
• bearophile (19/27) Jul 29 2013 As example take a look at this commit, a small part of the
• Robert Clipsham (14/23) Jul 29 2013 You can achieve this like so:
• Robert Clipsham (14/27) Jul 29 2013 What would be more interesting would be to have the ability to
• JS (20/50) Jul 30 2013 I don't think so, this seems similar:
• John Colvin (23/32) Aug 10 2013 I was initially unimpressed, but after some recent work I would
• JS (20/58) Aug 10 2013 And this is why just because something looks "unimpressive" to
• John Colvin (27/53) Aug 10 2013 That is laden with assumption.
• JS (24/80) Aug 10 2013 Well, again, the issue is that it only becomes one once you've
• JS (14/24) Aug 10 2013 so
• Artur Skawina (30/71) Aug 10 2013 template Tuple(A...) { alias Tuple = A; }
• JS (45/125) Aug 10 2013 a) thats your opinion.
• jerro (2/4) Aug 11 2013 Except, of course, the fact that one requires a language change
• JS (8/12) Aug 11 2013 and? How many language changes were done to D to make things more
• BS (10/10) Aug 11 2013 Man I love it when this Javascript bloke posts. The tantrums are
• Artur Skawina (10/36) Aug 11 2013 I can't think of a more subtle way to separate lists than using just
• Timon Gehr (1/1) Aug 10 2013 Guys, stop feeding the stupid troll now. He is not worth anyone's time.
• JS (3/5) Aug 10 2013 Yeah, who's the troll? Variadic grouping is useless says the
"JS" <js.mdnq gmail.com> writes:
```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

I doubt such a feature will ever get added but who knows...
```
Jul 29 2013
"bearophile" <bearophileHUGS lycos.com> writes:
```JS:

I doubt such a feature will ever get added but who knows...

It seems a cute idea, but why don't you show two or more very
different use cases? (Asking for a feature without showing use
cases is not so good.)

Bye,
bearophile
```
Jul 29 2013
"JS" <js.mdnq gmail.com> writes:
```On Monday, 29 July 2013 at 13:30:58 UTC, bearophile wrote:
JS:

I doubt such a feature will ever get added but who knows...

It seems a cute idea, but why don't you show two or more very
different use cases? (Asking for a feature without showing use
cases is not so good.)

Bye,
bearophile

The usefulness should be obvious and I seriously doubt if someone
thinks it is not then any example I could give would convince
them otherwise.

It came up for me trying to write a ternary if to use.

template tuple(args...) { alias tuple = args; }
template tMin(alias a, alias b)
{
static if (a < b) alias tMin = a; else alias tMin = b;
}

template tIf(alias cond, args...)
{
static if (sp < 0) enum spp = args.length; else enum spp = sp;
static if (cond) alias tIf = args[0..tMin!(\$, spp)];	else
alias tIf = args[tMin!(\$,spp+1)..\$];
}

I have to use tVariadicSplit to split the grouping(sure I could
reduce the symbol name size, which I have done).

Being able to write this as

template tIf(alias cond, tArgs..., fArgs...)
{
static if (cond)
alias tIf = tArgs;
else
alias tIf = fArgs;
}

Would be much much more elegant.
```
Jul 29 2013
"bearophile" <bearophileHUGS lycos.com> writes:
```JS:

The usefulness should be obvious and I seriously doubt if
someone thinks it is not then any example I could give would
convince them otherwise.

It's not obvious for me :-) Explaining the "obvious" is sometimes
necessary.

It came up for me trying to write a ternary if to use.

template tuple(args...) { alias tuple = args; }
template tMin(alias a, alias b)
{
static if (a < b) alias tMin = a; else alias tMin = b;
}

template tIf(alias cond, args...)
{
static if (sp < 0) enum spp = args.length; else enum spp = sp;
static if (cond) alias tIf = args[0..tMin!(\$, spp)];	else
alias tIf = args[tMin!(\$,spp+1)..\$];
}

(In your code I suggest to put a newline after each semicolon).

This is one use case, to implement a static ternary operator with
multiple arguments. (But having multiple arguments is not so
common).

A possible static ternary operator syntax:

enum foo = ct_cond !? Foo!5 : Bar!6;

But in my opinion the need for it is not strong enough, better to
keep the language simpler.

Do you have a second use case?

Bye,
bearophile
```
Jul 29 2013
"bearophile" <bearophileHUGS lycos.com> writes:
``` A possible static ternary operator syntax:

enum foo = ct_cond !? Foo!5 : Bar!6;

But in my opinion the need for it is not strong enough, better
to keep the language simpler.

A static ternary operator is sometimes handy, this is working
code:

import std.typetuple: TypeTuple;

template Iota(int n) {
static if (n <= 0)
alias TypeTuple!() Iota;
else
alias TypeTuple!(Iota!(n-1), n-1) Iota;
}

void main() {
int[3] a, b;
foreach (i; Iota!3)
a[i] = b[i];
}

With the recently introduced syntax for enum and templates you
could assume this works:

enum Iota(int n) = (n <= 0) ?
TypeTuple!() :
TypeTuple!(Iota!(n-1), n-1);

But that's a regular ternary operator, so despite only one branch
is computed, both are verified for type, because they have to
return the same type, so it gives:

Error: template instance test.Iota!-497 recursive expansion

A static ternary operator is allowed to return two different
types, so no type is computed for the other branch, and this
works:

enum Iota(int n) = (n <= 0) !?
TypeTuple!() :
TypeTuple!(Iota!(n-1), n-1);

Bye,
bearophile
```
Jul 29 2013
"JS" <js.mdnq gmail.com> writes:
```On Monday, 29 July 2013 at 13:59:54 UTC, bearophile wrote:
JS:

The usefulness should be obvious and I seriously doubt if
someone thinks it is not then any example I could give would
convince them otherwise.

It's not obvious for me :-) Explaining the "obvious" is
sometimes necessary.

It came up for me trying to write a ternary if to use.

template tuple(args...) { alias tuple = args; }
template tMin(alias a, alias b)
{
static if (a < b) alias tMin = a; else alias tMin = b;
}

template tIf(alias cond, args...)
{
static if (sp < 0) enum spp = args.length; else enum spp = sp;
static if (cond) alias tIf = args[0..tMin!(\$, spp)];	else
alias tIf = args[tMin!(\$,spp+1)..\$];
}

(In your code I suggest to put a newline after each semicolon).

This is one use case, to implement a static ternary operator
with multiple arguments. (But having multiple arguments is not
so common).

A possible static ternary operator syntax:

enum foo = ct_cond !? Foo!5 : Bar!6;

I suggested that a while back.

But in my opinion the need for it is not strong enough, better
to keep the language simpler.

Possibly because it doesn't exist? The problem is that when
working with recursion on variadic parameters you have to deal
with code like

t!(args[0], args[1..\$])

Sometimes you only want to return the last half of the args IF
something is true, e.g.,

t!(args[0], tIf!(cond, args[1..\$-2] else ";"));

or whatever. The problem being that args is a tuple and you can't
distinguish between what you want to return as true and what you
want to return as false.

To get around this you either have to create a split manually OR
write static if's that create a lot of redundant code.

Do you have a second use case?

Then a third? The fact whether there is a use case or not, or
whether I have one or not should be irrelevant. The issue should
stand on it's own. Having some easily way to use multiple
variadic parameters is either useful or not. If it is and not
hard to implement then it should be implemented. People can't use
something if it doesn't exist... and will find ways around the
real problem.

I think with a little work you could come up with many more and
better use cases than I could.  They all will related to a sort
of this or that scenario though because else why would one need
to split up the arguments in the first place if there was no need
to distinguish the group.

Join!(Strings...; Delims...)

could Join the strings with their Delims.

Map!(Objects...; Funcs...)

Could be an easy way to apply functions to objects.

most of these could be done by using a pair of values though but
would be easier to use multiple variadics.

Split!(Strings...; Splits...)

could split each strings with all the split possibilities.

e.g.

Split!("abcdefg", "abc"; "b", "c")

will split each string using each split.

returns

(["a", "defg"], ["a"])

Anyways, If you don't build it they won't come...
```
Jul 29 2013
"John Colvin" <john.loughran.colvin gmail.com> writes:
```On Monday, 29 July 2013 at 14:21:45 UTC, JS wrote:
Then a third? The fact whether there is a use case or not, or
whether I have one or not should be irrelevant. The issue
should stand on it's own. Having some easily way to use
multiple variadic parameters is either useful or not.

There are a mind-boggling large number of things that are useful,
but that's not the criteria for adding something to a programming
language.

A new feature has to be *sufficiently* useful to justify the
increased complexity of the language and it's implementations
(plus not clashing badly with other features). Example use cases
are a useful way of demonstrating just how useful a feature can
be.
```
Jul 29 2013
"monarch_dodra" <monarchdodra gmail.com> writes:
```On Monday, 29 July 2013 at 14:34:13 UTC, John Colvin wrote:
On Monday, 29 July 2013 at 14:21:45 UTC, JS wrote:
Then a third? The fact whether there is a use case or not, or
whether I have one or not should be irrelevant. The issue
should stand on it's own. Having some easily way to use
multiple variadic parameters is either useful or not.

There are a mind-boggling large number of things that are
useful, but that's not the criteria for adding something to a
programming language.

A new feature has to be *sufficiently* useful to justify the
increased complexity of the language and it's implementations
(plus not clashing badly with other features). Example use
cases are a useful way of demonstrating just how useful a
feature can be.

The need for "grouping variadics" creeps up every now and then,
and it *would* be useful to provide support for it. It may seem
like there isn't really a need, but it's not like a lot of people
do meta programming with recursive variadics. But for those that
*do* the requirement is obvious.

That said, it is *far* from requiring a language change.

A simple "Group" struct will solve the problem without a second
thought:

struct Group(Args...)
{
alias Ungroup = Args;
}

So, if we take into account that phobos already has a static if
for types (called select), it can become:

//----
void main()
{
enum a = false;
alias K = Select!(a, Group!(int, 1), Group!(double,
2)).Ungroup;
}
//----

"Group", contrary to Tuple, is not meant to ever be instanciated.
This makes it better in this scenario, as "Tuple!5" will not
compile (how do you construct an instance of type "5")? Another
advantage is that "Group" is an explicit type, which means you
can for a template that doesn't have "alias" parameters to accpet
values. EG:
Select!(cond, 1, 2);// This doesn't compile
Select!(a, Group!(1), Group!(2)).Ungroup; //But this does :)

It's a bit hackish, but it saves your butt.

The "issue" (I think) is that we don't have "Group" in phobos,
forcing our users (eg. JS), to re-invent and re-write the wheel,
over and over again, which is not great.

Placing this right under TypeTuple in std.typetuple seems ideal?
Should I submit a pull/ER ?
```
Jul 29 2013
"bearophile" <bearophileHUGS lycos.com> writes:
```monarch_dodra:

Select!(cond, 1, 2);// This doesn't compile

Time ago I asked for an improvement of Select:
https://github.com/D-Programming-Language/phobos/pull/1235

Maybe there is a way to allow that too:

template Select(bool condition, T...) if (T.length == 2) {
static if (condition)
enum Select = T[0];
else
enum Select = T[1];
}

void main() {
enum x = Select!(true, 10, 20);// error
static assert(x == 10);
int a = 1;
int b = 2;
alias y = Select!(true, a, b);
assert(y == 1);
alias T = Select!(true, int, long);
static assert(is(T == int));
}

How do you tell apart values from not values? :-)

Bye,
bearophile
```
Jul 29 2013
"bearophile" <bearophileHUGS lycos.com> writes:
``` How do you tell apart values from not values? :-)

Is this brutal enough? :-)

enum SameKind(T...) =
__traits(compiles, {enum x = T[0], y = T[1]; }) ||
__traits(compiles, {alias x = T[0]; alias y = T[1]; });

template Select(bool condition, T...)
if (T.length == 2 && SameKind!T) {
static if (__traits(compiles, {enum x = T[0];})) {
static if (condition)
enum Select = T[0];
else
enum Select = T[1];
} else {
static if (condition)
alias Select = T[0];
else
alias Select = T[1];
}
}

void main() {
enum x = Select!(true, 10, 20);
static assert(x == 10);
int a = 1;
int b = 2;
alias y = Select!(true, a, b);
assert(y == 1);
alias T = Select!(true, int, long);
static assert(is(T == int));
}

Bye,
bearophile
```
Jul 29 2013
"bearophile" <bearophileHUGS lycos.com> writes:
``` template Select(bool condition, T...)
if (T.length == 2 && SameKind!T) {
static if (__traits(compiles, {enum x = T[0];})) {
static if (condition)
enum Select = T[0];
else
enum Select = T[1];
} else {
static if (condition)
alias Select = T[0];
else
alias Select = T[1];
}
}

It works in simple cases and maybe it's worth changing in some
way the Select of Phobos, to support values too.
But to solve the problem in general I think there's a need for
"lazy template arguments", similar to lazy function arguments,
but for types.

template Select(condition, lazy T1, lazy T2) {...}

Bye,
bearophile
```
Jul 29 2013
"monarch_dodra" <monarchdodra gmail.com> writes:
```On Monday, 29 July 2013 at 15:31:39 UTC, bearophile wrote:
How do you tell apart values from not values? :-)

Is this brutal enough? :-)

enum SameKind(T...) =
__traits(compiles, {enum x = T[0], y = T[1]; }) ||
__traits(compiles, {alias x = T[0]; alias y = T[1]; });

template Select(bool condition, T...)
if (T.length == 2 && SameKind!T) {
static if (__traits(compiles, {enum x = T[0];})) {
static if (condition)
enum Select = T[0];
else
enum Select = T[1];
} else {
static if (condition)
alias Select = T[0];
else
alias Select = T[1];
}
}

void main() {
enum x = Select!(true, 10, 20);
static assert(x == 10);
int a = 1;
int b = 2;
alias y = Select!(true, a, b);
assert(y == 1);
alias T = Select!(true, int, long);
static assert(is(T == int));
}

Bye,
bearophile

But it's still "Select!(true, a, b)" and not "Select!(true, 1,
2)"...

template Select(bool condition, T1, T2)
{
static if (condition) alias Select = T1;
else                  alias Select = T2;
}
template Select(bool condition, alias T1, alias T2)
{
static if (condition) alias Select = T1;
else                  alias Select = T2;
}
template Select(bool condition, alias T1, T2)
{
static if (condition) alias Select = T1;
else                  alias Select = T2;
}
template Select(bool condition, T1, alias T2)
{
static if (condition) alias Select = T1;
else                  alias Select = T2;
}

*Now* Select!(condition, 1, 2) works.
```
Jul 29 2013
"monarch_dodra" <monarchdodra gmail.com> writes:
```On Monday, 29 July 2013 at 15:57:36 UTC, monarch_dodra wrote:
On Monday, 29 July 2013 at 15:31:39 UTC, bearophile wrote:
How do you tell apart values from not values? :-)

Is this brutal enough? :-)

enum SameKind(T...) =
__traits(compiles, {enum x = T[0], y = T[1]; }) ||
__traits(compiles, {alias x = T[0]; alias y = T[1]; });

template Select(bool condition, T...)
if (T.length == 2 && SameKind!T) {
static if (__traits(compiles, {enum x = T[0];})) {
static if (condition)
enum Select = T[0];
else
enum Select = T[1];
} else {
static if (condition)
alias Select = T[0];
else
alias Select = T[1];
}
}

void main() {
enum x = Select!(true, 10, 20);
static assert(x == 10);
int a = 1;
int b = 2;
alias y = Select!(true, a, b);
assert(y == 1);
alias T = Select!(true, int, long);
static assert(is(T == int));
}

Bye,
bearophile

But it's still "Select!(true, a, b)" and not "Select!(true, 1,
2)"...

Wait never mind my above post. Your approach works.
```
Jul 29 2013
"monarch_dodra" <monarchdodra gmail.com> writes:
```On Monday, 29 July 2013 at 16:00:47 UTC, monarch_dodra wrote:
Wait never mind my above post. Your approach works.

Except for this...
alias K = Select!(true, 4, int);

;)

Useful? I don't think so... but I thought I'd point it out ^^
```
Jul 29 2013
"Meta" <jared771 gmail.com> writes:
```On Monday, 29 July 2013 at 16:02:02 UTC, monarch_dodra wrote:
Except for this...
alias K = Select!(true, 4, int);

;)

Useful? I don't think so... but I thought I'd point it out ^^

I think it's a feature that this doesn't work. As for variadic
grouping, named parameters could easily solve this problem, and
have applications for other situations beside variadic arguments.
```
Jul 29 2013
"JS" <js.mdnq gmail.com> writes:
```On Monday, 29 July 2013 at 16:52:17 UTC, Meta wrote:
On Monday, 29 July 2013 at 16:02:02 UTC, monarch_dodra wrote:
Except for this...
alias K = Select!(true, 4, int);

;)

Useful? I don't think so... but I thought I'd point it out ^^

I think it's a feature that this doesn't work. As for variadic
grouping, named parameters could easily solve this problem, and
have applications for other situations beside variadic
arguments.

I'm not sure how named parameters would solve the original
problem but using a syntax like what I'm suggesting one can do
stuff like

template Log(alias cond, args...; string file = __FILE__, string
mod = __MODULE__)
{

}

which could be called without explicitly having to supply
__FILE__ and __MODULE__, currently you can't write such a CT

(although another solution would to have __PREVIOUS_FILE__,
__PREVIOUS_MODULE__, etc... that would return the file, module,
line number, etc.. of what called the template or function)

I think using the ';' notation is very concise and natural...
just that forgetting to use it could be very problematic.
```
Jul 29 2013
"Meta" <jared771 gmail.com> writes:
```On Monday, 29 July 2013 at 17:22:50 UTC, JS wrote:
I'm not sure how named parameters would solve the original
problem

template t(T1..., T2...)

...

t!(a, b, c; d, e, f);

Becomes

//Some weird hypothetical syntax
template t( name("T1") T1...,  name("T2") T2...)
{
...
}

t!(T1 = a, b, c, T2 = d, e, f);

but using a syntax like what I'm suggesting one can do stuff
like

...

I think these use cases would all work with named parameters.
```
Jul 29 2013
"JS" <js.mdnq gmail.com> writes:
```On Monday, 29 July 2013 at 17:28:57 UTC, Meta wrote:
On Monday, 29 July 2013 at 17:22:50 UTC, JS wrote:
I'm not sure how named parameters would solve the original
problem

template t(T1..., T2...)

...

t!(a, b, c; d, e, f);

Becomes

//Some weird hypothetical syntax
template t( name("T1") T1...,  name("T2") T2...)
{
...
}

t!(T1 = a, b, c, T2 = d, e, f);

but using a syntax like what I'm suggesting one can do stuff
like

...

I think these use cases would all work with named parameters.

I don't think that is very robust notation but if it is then it
would work.

Using ';' makes it obvious the next group is starting. In your
notation, it seems like there could be issues. What if T2 is a
local variable, then is that an assignment? If there is no
possible issues then I wouldn't mind having such a syntax...
anything is better than nothing.
```
Jul 29 2013
"Meta" <jared771 gmail.com> writes:
```On Monday, 29 July 2013 at 17:35:09 UTC, JS wrote:
I don't think that is very robust notation but if it is then it
would work.

Using ';' makes it obvious the next group is starting.

I think using f(..., name = ...) is pretty obvious, and possibly
easier to spot in a list of commas than `;`.

In your notation, it seems like there could be issues. What if
T2 is a local variable, then is that an assignment? If there is
no possible issues then I wouldn't mind having such a syntax...
anything is better than nothing.

I don't think it would be an issue, as it would work the same way
as local variables in functions that shadow those in an outer
scope.

import std.stdio;

void main()
{
int x = 2;
int test1(int x, int y)
{
return x + y;
}
auto n = test1(0, 1);

//Prints 1
writeln(n);
}

As for templates, I think you currently can't define templates
inside a function, so that wouldn't be an issue. As for using
this notation in a template argument list, I believe it works the
same way for templates.

alias T1 = int;

template t(T1)
{
alias t = T1;
}

void main()
{
//Prints "string"
pragma(msg, t!string);
}

alias T1 = TypeTuple!(int, string);

template t( name("T1") T1...,  name("T2") T2...)
{
alias t = T1;
}

void main()
{
//Should print (double, char)
pragma(msg, t!(T1 = double, char, T2 = bool));

//Should print (int, string)
pragma(msg, T1);
}
```
Jul 29 2013
"Meta" <jared771 gmail.com> writes:
```On Monday, 29 July 2013 at 17:52:41 UTC, Meta wrote:
In your notation, it seems like there could be issues. What if
T2 is a local variable, then is that an assignment? If there
is no possible issues then I wouldn't mind having such a
syntax... anything is better than nothing.

I don't think it would be an issue, as it would work the same
way as local variables in functions that shadow those in an
outer scope.

...

Actually, I think I misunderstood your meaning. You're right,
this could be a problem. Currently:

import std.stdio;

void main()
{
int x = 0;
int test(int x, int y)
{
return x + y;
}
//Prints 2
writeln(test(x = 1, 1));
//Prints 1
writeln(x);
}

So in a hypothetical situation where we now have named parameters:

import std.stdio;

void main()
{
int x = 0;
int test( name("x") x,  name("y") y)
{
return x + y;
}
//Prints 3
writeln(test(x = 1, y = 2));
//What does this print?
writeln(x);
}
```
Jul 29 2013
Artur Skawina <art.08.09 gmail.com> writes:
```On 07/29/13 17:24, bearophile wrote:
Maybe there is a way to allow that too:

template Select(bool condition, T...) if (T.length == 2) {
static if (condition)
enum Select = T[0];
else
enum Select = T[1];
}

void main() {
enum x = Select!(true, 10, 20);// error
static assert(x == 10);
int a = 1;
int b = 2;
alias y = Select!(true, a, b);
assert(y == 1);
alias T = Select!(true, int, long);
static assert(is(T == int));
}

How do you tell apart values from not values? :-)

template Select(bool condition, T...) if (T.length == 2) {
static if (__traits(compiles, function { alias _1 = T[0]; alias _2 =
T[1]; }))
alias Select = T[!condition];
else
enum Select = T[!condition];
}

artur
```
Jul 29 2013
Artur Skawina <art.08.09 gmail.com> writes:
```On 07/29/13 22:43, Artur Skawina wrote:
On 07/29/13 17:24, bearophile wrote:
Maybe there is a way to allow that too:

template Select(bool condition, T...) if (T.length == 2) {
static if (condition)
enum Select = T[0];
else
enum Select = T[1];
}

void main() {
enum x = Select!(true, 10, 20);// error
static assert(x == 10);
int a = 1;
int b = 2;
alias y = Select!(true, a, b);
assert(y == 1);
alias T = Select!(true, int, long);
static assert(is(T == int));
}

How do you tell apart values from not values? :-)

template Select(bool condition, T...) if (T.length == 2) {
static if (__traits(compiles, function { alias _1 = T[0]; alias _2 =
T[1]; }))
alias Select = T[!condition];
else
enum Select = T[!condition];
}

Or even:

template Select(bool condition, T...) if (T.length == 2) {
static if (__traits(compiles, function { alias _ = T[!condition]; }))
alias Select = T[!condition];
else
enum Select = T[!condition];
}

but that's a bit /too much/ magic -- allowing

alias y1 = Select!(true, b, int);
assert(y1 == 2);
alias y2 = Select!(false, b, int);
assert(is(y2==int));

is "neat", but could be confusing...

artur
```
Jul 29 2013
"Dicebot" <public dicebot.lv> writes:
```On Monday, 29 July 2013 at 14:53:10 UTC, monarch_dodra wrote:
A simple "Group" struct will solve the problem without a second
thought:

struct Group(Args...)
{
alias Ungroup = Args;
}

That is actually a TypeTuple that does not auto-expand. May be
even worth defining it as "alias Ungroup = TypeTuple!(Args)" to
be more self-documenting at cost of some redundancy.

Also it does not need to be a struct, templates are not mandatory
eponymous.

I think it is best solution for topic starter problem in terms of
ROI and worth inclusion into Phobos.
```
Jul 30 2013
Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
```On 7/30/13 12:36 AM, Dicebot wrote:
On Monday, 29 July 2013 at 14:53:10 UTC, monarch_dodra wrote:
A simple "Group" struct will solve the problem without a second thought:

struct Group(Args...)
{
alias Ungroup = Args;
}

That is actually a TypeTuple that does not auto-expand. May be even
worth defining it as "alias Ungroup = TypeTuple!(Args)" to be more
self-documenting at cost of some redundancy.

Also it does not need to be a struct, templates are not mandatory
eponymous.

I think it is best solution for topic starter problem in terms of ROI
and worth inclusion into Phobos.

Agreed.

Andrei
```
Jul 30 2013
"bearophile" <bearophileHUGS lycos.com> writes:
```John Colvin:

There are a mind-boggling large number of things that are
useful, but that's not the criteria for adding something to a
programming language.

A new feature has to be *sufficiently* useful to justify the
increased complexity of the language and it's implementations
(plus not clashing badly with other features). Example use
cases are a useful way of demonstrating just how useful a
feature can be.

As example take a look at this commit, a small part of the
changes to port the D front-end to D:
https://github.com/D-Programming-Language/dmd/compare/428e559e5f0b...68ab05dba14a

In this original line 'errors' is a boolean:
errors += global.endGagging(oldGaggedErrors);

It's replaced with:
if (global.endGagging(oldGaggedErrors))
errors = true;

Looking at that code it's easy to think about code like this,
that is not currently supported:

errors ||= global.endGagging(oldGaggedErrors);

Is the "||=" operator useful? Is it working well with the rest of
the language? Is it easy to understand a read? It is not
bug-prone given the existence of the "|=" operator? Even if all
those answers are positive, you have to ask yourself if it's also
sufficiently useful...

Bye,
bearophile
```
Jul 29 2013
Artur Skawina <art.08.09 gmail.com> writes:
```On 07/29/13 17:03, bearophile wrote:
errors += global.endGagging(oldGaggedErrors);

It's replaced with:
if (global.endGagging(oldGaggedErrors))
errors = true;

Looking at that code it's easy to think about code like this, that is not
currently supported:

errors ||= global.endGagging(oldGaggedErrors);

Is the "||=" operator useful?

Not really.

errors |=!! global.endGagging(oldGaggedErrors);

artur
```
Jul 29 2013
"Robert Clipsham" <robert octarineparrot.com> writes:
```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

I doubt such a feature will ever get added but who knows...

You can achieve this like so:
----
template Outer(T...) {
template Inner(U...) {
// Do something with T and U
}
}
Outer!(a, b, c).Inner!(d, e, f);
----

You can see an example of it in action here (type tuple
intersection):
https://github.com/mrmonday/misc/blob/master/misc/misc.d#L5

Robert
```
Jul 29 2013
"Robert Clipsham" <robert octarineparrot.com> writes:
```On Monday, 29 July 2013 at 14:46:02 UTC, Robert Clipsham wrote:
You can achieve this like so:
----
template Outer(T...) {
template Inner(U...) {
// Do something with T and U
}
}
Outer!(a, b, c).Inner!(d, e, f);
----

You can see an example of it in action here (type tuple
intersection):
https://github.com/mrmonday/misc/blob/master/misc/misc.d#L5

Robert

What would be more interesting would be to have the ability to
----
template Outer(T...) {
template Inner(U... ...) {
// Do something with T, U[0], U[1], U[2..\$]
}
}
Outer!(a, b, c).Inner!(d, e, f).Inner!(g, h, i); // Etc
----
```
Jul 29 2013
"JS" <js.mdnq gmail.com> writes:
```On Monday, 29 July 2013 at 15:02:13 UTC, Robert Clipsham wrote:
On Monday, 29 July 2013 at 14:46:02 UTC, Robert Clipsham wrote:
You can achieve this like so:
----
template Outer(T...) {
template Inner(U...) {
// Do something with T and U
}
}
Outer!(a, b, c).Inner!(d, e, f);
----

You can see an example of it in action here (type tuple
intersection):
https://github.com/mrmonday/misc/blob/master/misc/misc.d#L5

Robert

What would be more interesting would be to have the ability to
----
template Outer(T...) {
template Inner(U... ...) {
// Do something with T, U[0], U[1], U[2..\$]
}
}
Outer!(a, b, c).Inner!(d, e, f).Inner!(g, h, i); // Etc
----

I don't think so, this seems similar:

It would be cool if we could nest templates to get grouping

template tIF(alias cond)
{
template tIF(alias T...)
{
template tIF(alias F...)
{
....
}
}

then do

tIF!(cond)!(t1,t2,t3)!(f1,..,fn)

which would allow for a natural grouping of variadics. The
notation may seem silly but only because it is not common.

which could have a short hand notation of

tIF!(cond; t1, t2, t3; f1, ..., fn);

(this way, if you can't keep track of your ';'s then you can use
the long form)
```
Jul 30 2013
"John Colvin" <john.loughran.colvin gmail.com> writes:
```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

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))
```
Aug 10 2013
"JS" <js.mdnq gmail.com> writes:
```On Saturday, 10 August 2013 at 10:19:34 UTC, 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

I doubt such a feature will ever get added but who knows...

I was initially unimpressed, but after some recent work I would

And this is why just because something looks "unimpressive" to
you doesn't mean it is... Obviously if you've never run up
against the specific problems proposed by people you won't know
how frustrating it is, specially when there is an easy fix. This
is why those commie bastards that shoot suggestions down at first
sight ruin progress... they don't have the experience with the
specific issue to know just how much it sucks.

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

EXACTLY! Why the hell would I want to go around doing the stuff
below all the time when there is a perfectly fine notation(above)
for it? Just because deadlinx, or dicebot, or whoever wants to be
close minded about it because they themselves haven't constantly
ran into the issue.

It's very easy to write off someone elses issues because you
yourself don't have the problems but it shows a lot of arrogance.

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))

Even better, you can use something like A!(int, long, double,
_S_, Point, int)

where _S_ acts as the `;`. Not great, but in my opinion it is
simpler than the grouping and ungrouping. (you can write a
utility function to convert between them).
```
Aug 10 2013
"John Colvin" <john.loughran.colvin gmail.com> writes:
```On Saturday, 10 August 2013 at 12:40:55 UTC, JS wrote:
On Saturday, 10 August 2013 at 10:19:34 UTC, 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

I doubt such a feature will ever get added but who knows...

I was initially unimpressed, but after some recent work I would

And this is why just because something looks "unimpressive" to
you doesn't mean it is... Obviously if you've never run up
against the specific problems proposed by people you won't know
how frustrating it is, specially when there is an easy fix.
This is why those commie bastards that shoot suggestions down
at first sight ruin progress... they don't have the experience
with the specific issue to know just how much it sucks.

I had run in to the problem before, several times. I was not
initially convinced your suggestion was a good idea, especially
after monarch dodra posted Group. After some more experience and
thought I have now changed my mind.

Anyway, never mind all that, what matters is the proposal.

I think this proposal is a good idea, or at least that there
should be some simple syntax for doing this sort of thing. In
particular I'd be interested in hearing from bearophile about how
it might fit in with his wider ideas on tuples and syntax for
packing/unpacking.

Also, are there any corner cases that haven't been considered.

alias T = Tuple!(int, int);
alias Ts = Tuple!(T, T);

template A(S0..., S1...)
{
alias s0 = S0;
alias s1 = S1;
}

A!(Ts.init).s0 a;

what types are a/s0 and s1?

s0 == Tuple!(int, int) == s1

or

s0 == Tuple!(Tuple!(int, int), Tuple!(int, int))
and s1 is an empty tuple

i.e. what will the rules for auto-expansion/unpacking be?
```
Aug 10 2013
"JS" <js.mdnq gmail.com> writes:
```On Saturday, 10 August 2013 at 17:08:57 UTC, John Colvin wrote:
On Saturday, 10 August 2013 at 12:40:55 UTC, JS wrote:
On Saturday, 10 August 2013 at 10:19:34 UTC, 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

I doubt such a feature will ever get added but who knows...

I was initially unimpressed, but after some recent work I
would

And this is why just because something looks "unimpressive" to
you doesn't mean it is... Obviously if you've never run up
against the specific problems proposed by people you won't
know how frustrating it is, specially when there is an easy
fix. This is why those commie bastards that shoot suggestions
down at first sight ruin progress... they don't have the
experience with the specific issue to know just how much it
sucks.

I had run in to the problem before, several times. I was not
initially convinced your suggestion was a good idea, especially
after monarch dodra posted Group. After some more experience
and thought I have now changed my mind.

Anyway, never mind all that, what matters is the proposal.

Well, again, the issue is that it only becomes one once you've
actually experienced the problem enough. This is why those that
actually haven't even run into the problem shouldn't really have
a say so if it is valid or not, unless they can bring some
theoretical reason why it is flawed.

I think this proposal is a good idea, or at least that there
should be some simple syntax for doing this sort of thing. In
particular I'd be interested in hearing from bearophile about
how it might fit in with his wider ideas on tuples and syntax
for packing/unpacking.

Also, are there any corner cases that haven't been considered.

alias T = Tuple!(int, int);
alias Ts = Tuple!(T, T);

template A(S0..., S1...)
{
alias s0 = S0;
alias s1 = S1;
}

A!(Ts.init).s0 a;

what types are a/s0 and s1?

s0 == Tuple!(int, int) == s1

or

s0 == Tuple!(Tuple!(int, int), Tuple!(int, int))
and s1 is an empty tuple

i.e. what will the rules for auto-expansion/unpacking be?

The way I see it, using `;` is what separates groups. So in your
above code, s1 is empty.

The `;` is shorthand for specifying groups. No where do you
specify such a group for A!(...), so there are no groups.

There is no direct way to get your second case under my
proposal... unless the compiler was given some additional feature
to do so.

e.g.,

alias Ts = Tuple!(T, T);

is not the same as

alias Ts = Tuple!(T; T);

also, we would probably want to use template A(S0...; S1...)

The main thing is that `;` adds an extra symbol to split on that
is entirely distinct from `,`. If you wanted, you could have
Tuple! and TupleSC!. TupleSC! is used when splitting `;`. Tuple!
and TupleSC! are not directly related(but can easily be flattened
together if necessary.
```
Aug 10 2013
"JS" <js.mdnq gmail.com> writes:
```  alias T = Tuple!(int, int);
alias Ts = Tuple!(T, T);

template A(S0..., S1...)
{
alias s0 = S0;
alias s1 = S1;
}

A!(Ts.init).s0 a;

so

alias T = Tuple!(int, int);
alias Ts = TupleSC!(T, T);

then Ts == ((int, int); (int, int))

and

alias T = TupleSC!(int, int);
alias Ts = Tuple!(T, T);

(int; int), (int; int))

and

alias T = TupleSC!(int, int);
alias Ts = TupleSC!(T, T);

(int; int); (int; int))

which all can be written longhand as TupleY!(TupleX!(int,int),
TupleX!(int,int)).
```
Aug 10 2013
Artur Skawina <art.08.09 gmail.com> writes:
```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
```
Aug 10 2013
"JS" <js.mdnq gmail.com> writes:
```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

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

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.

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)
```
Aug 10 2013
"jerro" <a a.com> writes:
``` Group!() and (); are the same except one is shorter and IMO
more convienent... there is otherwise, no other difference.

Except, of course, the fact that one requires a language change
and the other doesn't.
```
Aug 11 2013
"JS" <js.mdnq gmail.com> writes:
```On Sunday, 11 August 2013 at 08:32:35 UTC, jerro wrote:
Group!() and (); are the same except one is shorter and IMO
more convienent... there is otherwise, no other difference.

Except, of course, the fact that one requires a language change
and the other doesn't.

and? How many language changes were done to D to make things more
mentioned it as a feature for D.

"This can be done by making a symbol and breaking up a single

Using Group is messy. I know some people like messy code but that
shouldn't require everyone to write messy code.
```
Aug 11 2013
"BS" <slackovsky gmail.com> writes:
```Man I love it when this Javascript bloke posts. The tantrums are
brilliant :-)

JS: Why does D not do X, it should and without it D is useless.
Implement my minions!
DD: Why should X be implemented? Show us some example where it
would be useful.
JS: You are an ignorant stupid fool if you cannot see the
benefit. And obviously too lazy to figure out an example yourself.

Here's your dummy JS, but please keep spitting it. It gives me
```
Aug 11 2013
Artur Skawina <art.08.09 gmail.com> writes:
```On 08/11/13 04:07, JS wrote:
On Saturday, 10 August 2013 at 18:28:39 UTC, Artur Skawina wrote:
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.

I can't think of a more subtle way to separate lists than using just
a single pixel. I know -- I should try harder.

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.

that Group!() is any different than `;` as far as logic goes?

Yes.

If so then you really need to learn to think abstractly.

Won't help in this case.

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.

Wasn't ';' enough?

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 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)

template A(T...) { pragma(msg, T); }
alias B = A!("one", (2.0, "three"));

artur
```
Aug 11 2013
Timon Gehr <timon.gehr gmx.ch> writes:
```Guys, stop feeding the stupid troll now. He is not worth anyone's time.
```
Aug 10 2013
"JS" <js.mdnq gmail.com> writes:
```On Sunday, 11 August 2013 at 03:14:46 UTC, Timon Gehr wrote:
Guys, stop feeding the stupid troll now. He is not worth
anyone's time.

Yeah, who's the troll? Variadic grouping is useless says the
troll.
```
Aug 10 2013