See http://www.digitalmars.com/d/variadic-function-templates.html
Why now? Because it's such a pain to do template programming without
them, and because I wanted to have a good signals and slots
implementation. That was the last piece needed to make S&S work right
(unless I'm way off track with it).
There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

This looks excellent. Supporting both a head-tail recursive variant and the
indexable/foreachable tuple is brilliant. This will tremendously simplify
much of my code and remove the hard limits on number of arguments.
I also wish dmd gets better at inlining long chains of recursive template
functions.

There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

I am really excited about the possibilities here. Will tuples become real
types or a meta-types?
From the examples you show, I'd presume there is an implicit tuple expansion
when calling
void foo(int a, int b) {}
as foo(t); where t is a tuple of (int,int) ?
will it be possible to declare a function such as taking a specific tuple
argument and use tuples as return values etc?
As I said, I think this looks great. We are no longer in the vicinity of D
1.0... We are already at 2.0 :)
/Oskar

There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

I am really excited about the possibilities here. Will tuples become real
types or a meta-types?

My current thought is that they will never be types, i.e. you will not
be able to have a "pointer to tuple" or "array of tuples". Also, they
will always be statically fixed at compile time. A tuple will simply be
a shorthand notation for a sequence of types or expressions.

From the examples you show, I'd presume there is an implicit tuple expansion
when calling
void foo(int a, int b) {}
as foo(t); where t is a tuple of (int,int) ?

That's right. Those two declarations are the same thing. A function
parameter list is a tuple.

will it be possible to declare a function such as taking a specific tuple
argument

I'm not sure what you mean. A function's parameter types *are* a tuple.

There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

I am really excited about the possibilities here. Will tuples become real
types or a meta-types?

My current thought is that they will never be types, i.e. you will not
be able to have a "pointer to tuple" or "array of tuples". Also, they
will always be statically fixed at compile time. A tuple will simply be
a shorthand notation for a sequence of types or expressions.

From the examples you show, I'd presume there is an implicit tuple expansion
when calling
void foo(int a, int b) {}
as foo(t); where t is a tuple of (int,int) ?

That's right. Those two declarations are the same thing. A function
parameter list is a tuple.

What about the comma operator? It would be perfect for creating tuples,
and very consistent with the way functions are called. For example
print(7,'a',6.8) passes to tuple (7,'a',6.8) to the function print.
L.

What about the comma operator? It would be perfect for creating tuples,
and very consistent with the way functions are called. For example
print(7,'a',6.8) passes to tuple (7,'a',6.8) to the function print.

What about the comma operator? It would be perfect for creating tuples,
and very consistent with the way functions are called. For example
print(7,'a',6.8) passes to tuple (7,'a',6.8) to the function print.
L.

What about the comma operator? It would be perfect for creating tuples,
and very consistent with the way functions are called. For example
print(7,'a',6.8) passes to tuple (7,'a',6.8) to the function print.
L.

Did you mean like this.
tuple t=7,'a',6.8;
print(t);

Yes, possible needing the () to prevent ambiguity with declaration of
multiple variables.

See http://www.digitalmars.com/d/variadic-function-templates.html
Why now? Because it's such a pain to do template programming without
them, and because I wanted to have a good signals and slots
implementation. That was the last piece needed to make S&S work right
(unless I'm way off track with it).
There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

This is great! I've already thought of a number of ways to vastly
improve the metaprogramming stuff I'm using in Pyd. (Sigh... and I just
re-wrote all of that once already.) Pyd is a great use-case for an MPL,
and I've been compiling a pretty decent one while writing it (with great
work from h3r3tic and Don and others). I think it's about to get a whole
lot more interesting...
--
Kirk McDonald
Pyd: Wrapping Python with D
http://pyd.dsource.org

See http://www.digitalmars.com/d/variadic-function-templates.html
Why now? Because it's such a pain to do template programming without
them, and because I wanted to have a good signals and slots
implementation. That was the last piece needed to make S&S work right
(unless I'm way off track with it).
There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

This is great! I've already thought of a number of ways to vastly
improve the metaprogramming stuff I'm using in Pyd. (Sigh... and I just
re-wrote all of that once already.) Pyd is a great use-case for an MPL,
and I've been compiling a pretty decent one while writing it (with great
work from h3r3tic and Don and others). I think it's about to get a whole
lot more interesting...

In trying to work with the variadic templates, I've discovered a few
weaknesses and bugs.
1) Index in static foreach is not const
Take this template function:
void foo(T ...)(T t) {
foreach (i, arg; t) {
t[i] = something_else;
}
}

Assertion failure: 'global.errors' on line 2752 in file 'template.c'
abnormal program termination
I had other complaints, but these are the only ones that occur to me at
the moment.
--
Kirk McDonald
Pyd: Wrapping Python with D
http://pyd.dsource.org

See http://www.digitalmars.com/d/variadic-function-templates.html
Why now? Because it's such a pain to do template programming without
them, and because I wanted to have a good signals and slots
implementation. That was the last piece needed to make S&S work right
(unless I'm way off track with it).
There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

Is it possible to restrict use type specialization to restrict a tuple
to a specific type? I'm no template guru, but the things I've been
toying around with don't work and I don't see anything in the docs about it.

See http://www.digitalmars.com/d/variadic-function-templates.html
Why now? Because it's such a pain to do template programming without
them, and because I wanted to have a good signals and slots
implementation. That was the last piece needed to make S&S work right
(unless I'm way off track with it).
There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

Is it possible to restrict use type specialization to restrict a tuple
to a specific type? I'm no template guru, but the things I've been
toying around with don't work and I don't see anything in the docs about
it.

See http://www.digitalmars.com/d/variadic-function-templates.html
Why now? Because it's such a pain to do template programming without
them, and because I wanted to have a good signals and slots
implementation. That was the last piece needed to make S&S work right
(unless I'm way off track with it).
There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

Perhaps boost fusion is one example where this territory is explored.
I'm very curious to see what some D programmers will do with this.
Two minor mistakes in the examples from
http://www.digitalmars.com/d/template.html:
Write!(int, char, double).print(1, 'a', 6.8); // prints: args are 1a6.8
should be: Write!(int, char, double).write(1, 'a', 6.8);
And:
void Foo(T t, R r)
{
writefln(t);
if (r.length) // if more arguments
Foo(r); // do the rest of the arguments
}
should be:
void Foo(T t, R r)
{
writefln(t);
static if (r.length)// if more arguments
Foo(r); // do the rest of the arguments
}

See http://www.digitalmars.com/d/variadic-function-templates.html
Why now? Because it's such a pain to do template programming without
them, and because I wanted to have a good signals and slots
implementation. That was the last piece needed to make S&S work right
(unless I'm way off track with it).
There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

I'm glad you could get that to work!
But why not force "static" before the "foreach"?
L.

See http://www.digitalmars.com/d/variadic-function-templates.html
Why now? Because it's such a pain to do template programming without
them, and because I wanted to have a good signals and slots
implementation. That was the last piece needed to make S&S work right
(unless I'm way off track with it).
There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

I'm glad you could get that to work!
But why not force "static" before the "foreach"?

Because 'a' is a run-time construct. It's a bit weird, but think of
tuples (ie. variadric templates) like static arrays. You know their
length and element types at compile-time and so can use static if, etc,
for processing some bits then. But they are also a run-time construct
in that actual data is being passed around, so iterating across the data
uses foreach. That said, it would be kind of nice to have static
foreach work on the contents of static arrays, tuples containing
constants, type lists, etc. This could make creating factory classes
extremely simple.
Sean

See http://www.digitalmars.com/d/variadic-function-templates.html
Why now? Because it's such a pain to do template programming without
them, and because I wanted to have a good signals and slots
implementation. That was the last piece needed to make S&S work right
(unless I'm way off track with it).
There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

This feature seems to supercede older versions of variadic functions. Are
there still reasons to use the older approach to variadics? If not, should
any of the older approaches ever be deprecated in order to simplify the D
language?
-Craig

This feature seems to supercede older versions of variadic functions. Are
there still reasons to use the older approach to variadics? If not, should
any of the older approaches ever be deprecated in order to simplify the D
language?

That's a very good question, and I don't know the answer. writefln()'s
current implementation may be obsolete. But it's premature to write its
obituary. Let's see how things unfold a bit first.

Craig Black wrote:
>> This feature seems to supercede older versions of variadic functions.
>> Are there still reasons to use the older approach to variadics?
Walter Bright wrote:

That's a very good question, and I don't know the answer.
writefln()'s current implementation may be obsolete. But it's
premature to write its obituary. Let's see how things unfold a bit
first.

I'd hate to think that every call to a variadic function would require
a template instantiation. Doesn't seem like it'd be very efficient.
--benji

Wait, templating function calls incurs a runtime penalty?

To some extent, yes. having templated function increases the memory
footprint and working set of the program and can cause more swapping and
cash misses.
Another problem with deprecating varidic function would be the template
varidic functions have different types:
<code>
// silly example
void function(...) printer;
if(hasEOL)
printer = &writef;
else
printer = &writefln;
printer("the first thing is: %s", GetString());
printer("the second thing is: %s", GetOtherString());
</code>
The problem is that template varidics operate at compile time, not run time.

This feature seems to supercede older versions of variadic functions.
Are there still reasons to use the older approach to variadics? If
not, should any of the older approaches ever be deprecated in order to
simplify the D language?

That's a very good question, and I don't know the answer. writefln()'s
current implementation may be obsolete. But it's premature to write its
obituary. Let's see how things unfold a bit first.

Definitely too early to kill runtime variadics just because there are
now compile time ones. writefln is an especially good example of why
not. In a stdio heavy app it can get called in thousands of different
ways with different combination of argument types. Do you really want
each of those to be a separately instantiated function? It may run
slightly faster but the code size will be huge. No, writefln
definitely still has a place as-is.
--bb

This feature seems to supercede older versions of variadic functions. Are
there still reasons to use the older approach to variadics? If not, should
any of the older approaches ever be deprecated in order to simplify the D
language?
-Craig

I think that we can get rid of old varargs, and here's why:
The only feature-wise differences I can see between old varargs and new
variadic templates is that old varargs can be done without the
source-code present, and old varargs can be a virtual function of a class.
We can address both of these concerns with wrapper functions and an
additional Phobos library:
// This would be part of Phobos
struct varargData
{
TypeInfo[] ti;
void* argptr;
}
varargData getVarargData(T...) (T t)
{
varargData info;
with (info)
foreach (t; a)
{
ti ~= typeid(t);
argptr ~= cast(void*)t[0..t.sizeof]; // I'm not sure if this is
right, but you get the idea
}
return info;
}
// This would be the wrapper function of the closed-source library.
// The wrapper is open source, but doesn't expose any algorithmic details.
// This is analogous to C++ header files.
void opensourceWrapper(T...) (T t)
{
auto data = getVarargData(t);
closedFoo(data);
}
// We could create a 'final' wrapper function within a class:
class Foo
{
final void foo(T...) (T t)
{
auto data = getVarargData(t);
virtualFoo(data);
}
// Subclasses override this
void virtualFoo(varargData data) {...}
}
So, the same functionality as old varargs can be achieved with new
varargs, with a small pattern on the declaration site. I assert that the
need for this pattern will be sufficiently small (since vararg functions
are quite rare, and they are generally better to implement with
templates anyway) that this syntactic sugar (old varargs) can be removed
from the language.
Furthermore, this pattern is simple enough that it should be possible to
express with a sufficiently powerful macro system. Unfortunately, the
lack of string pasting in macros means that making differently-named
wrappers is not possible at the moment.
Cheers,
Reiner

This feature seems to supercede older versions of variadic functions.
Are there still reasons to use the older approach to variadics? If
not, should any of the older approaches ever be deprecated in order to
simplify the D language?
-Craig

I think that we can get rid of old varargs, and here's why:
The only feature-wise differences I can see between old varargs and new
variadic templates is that old varargs can be done without the
source-code present, and old varargs can be a virtual function of a class.
We can address both of these concerns with wrapper functions and an
additional Phobos library:
// This would be part of Phobos
struct varargData
{
TypeInfo[] ti;
void* argptr;
}
varargData getVarargData(T...) (T t)
{
varargData info;
with (info)
foreach (t; a)
{
ti ~= typeid(t);
argptr ~= cast(void*)t[0..t.sizeof]; // I'm not sure if this is
right, but you get the idea
}
return info;
}
// This would be the wrapper function of the closed-source library.
// The wrapper is open source, but doesn't expose any algorithmic details.
// This is analogous to C++ header files.
void opensourceWrapper(T...) (T t)
{
auto data = getVarargData(t);
closedFoo(data);
}
// We could create a 'final' wrapper function within a class:
class Foo
{
final void foo(T...) (T t)
{
auto data = getVarargData(t);
virtualFoo(data);
}
// Subclasses override this
void virtualFoo(varargData data) {...}
}
So, the same functionality as old varargs can be achieved with new
varargs, with a small pattern on the declaration site. I assert that the
need for this pattern will be sufficiently small (since vararg functions
are quite rare, and they are generally better to implement with
templates anyway) that this syntactic sugar (old varargs) can be removed
from the language.
Furthermore, this pattern is simple enough that it should be possible to
express with a sufficiently powerful macro system. Unfortunately, the
lack of string pasting in macros means that making differently-named
wrappers is not possible at the moment.
Cheers,
Reiner

No, I don't think it does. You could get away with this, though:
interface ILogger
{
void log_msg_impl(char[] fmt, varargData data);
}
void log_msg(T...) (ILogger logger, char[] fmt, T t)
{
auto data = getVarargData(t);
logger.log_msg_impl(fmt, data);
}
If the implicit-this syntax sugar we have for arrays (which allows
"foo".toupper) was allowed for all types, then this discrepancy would
disappear, and you could write the call as if were a member function:
myLogger.log_msg("foo: %d", foo);
as opposed to
log_msg(myLogger, "foo: %d", foo);
Cheers,
Reiner

See http://www.digitalmars.com/d/variadic-function-templates.html
Why now? Because it's such a pain to do template programming without
them, and because I wanted to have a good signals and slots
implementation. That was the last piece needed to make S&S work right
(unless I'm way off track with it).
There's a lot of unexplored territory with the tuples, they should be
able to do a lot more than the current rather limited ability.

Cool, it really quite helps the (many) template code out there that had
to replicate code for each number of parameters it wanted to support.
Also, tuples are quite a good framework to implement compile-time
reflection upon. For example, something more or less like this:
struct Foo {
int x, y;
void func(int a) {}
}
...
foo = new Foo();
// Then any kind of aggregate has a membersTuple property where
// each membersTuple element is an alias to the member
foo.membersTuple[0]++; //foo.membersTuple[0] same as foo.x
foo.membersTuple[1]--; //foo.membersTuple[1] same as foo.y
foo.membersTuple[2](42); //foo.membersTuple[2] same as foo.func
Then we could have generic serializers (and other stuff) like:
template serialize( TYPE ) {
void serialize(TYPE t ) {
foreach(member; t.membersTuple) {
// Check to see if the member is a field
// and not a method or an inner type:
static if( !is(member) && !is(member == function) ) {
writeln("member: ", typeid(typeof(member)), " value: ", member);
}
}
}
}
--
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D

That's because you can't have executable statements in a template. I
really wish you could, tho.
If you want to write those out at COMPILE TIME, however, you can change

writefln(s);

To:

pragma(msg, s);

-- Daniel
--
Unlike Knuth, I have neither proven or tried the above; it may not even
make sense.
v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D
i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/