March 26, 2004
So let's say I have a function that I want to take an arbitrary number of arguments. Actually, I do, so I'll get specific. The function's name is TableRow, and its first argument is a StreamSocket, and after that it takes an arbitrary number of args, converts them all to strings (if they aren't already), and constructs a table row in HTML (writing it into a string) and sends it to the StreamSocket (which is connected to a web-browser).

'params' is a keyword in C# which indicates to the compiler that someone can call this function with an arbitrary number of arguments (after all the required ones to the left of the params argument), and they'll be corralled into an array which the function will use. Technically this doesn't add special code to the function with params - it just expects an array for that argument - It tells the compiler to do evil things to all the code which *calls* that function, to make it corral all the arguments it wants to send into an array and use that as a parameter.

In c++ I'd have had to do some voodoo with va_something_or_other which I never fully understood; The C# way makes far more sense to me (Although the way it's implemented seems slightly odd to me).

In any event, I didn't happen to notice anything like this in the D spec, so I figured I'd ask here: Does anything like this exist in D? If not, are there plans to have such a thing? (In the mean-time, I can try to write TableRow(s, [p.orbit, p.sendheat, p.gas, p.h2o, p.water, p.ice, p.vapor, p.land, p.heat, p.surfaceArea, p.volume, p.mass]); instead of TableRow(s, p.orbit, p.sendheat, p.gas, p.h2o, p.water, p.ice, p.vapor, p.land, p.heat, p.surfaceArea, p.volume, p.mass); :P )

Hmmm. And now it occurs to me that I probably have to do TableRow(StreamSocket, char[][]) as well as TableRow(StreamSocket, real[]) and can't do TableRow(StreamSocket, object[]) and call toString() on it, since real etc don't have toString members ooorr.... Hmmmm. Is real/int/double/etc even descended from object in D? (Probably not, right?)

Thanks,
-SL
March 26, 2004
Posted a while back buried deep in a thread about C# is the template

private import std.c.stdio;
template va_array(T:T[])
{
   T[] va_array(uint* ptr)
   {
      T* args = cast(T*)(cast(va_list)ptr + uint.size);
      return args[0 .. *ptr];
   }
}

(well, actually I modified the declaration a tiny bit)
To use it pass the number of args and then just list the arguments
making sure they are the right type. For example:

void
someFunc(int x, double y, uint num_args, ...)
{
   char[][] args = va_array!(char[][])(&num_args);
   // do whatever you want with args
   foreach (char[] str; args)
      printf("%.*s\n",str);
}

int
main()
{
    someFunc(0,1.0,3,"hello","world","goodbye");
    return 0;
}

This will call someFunc with 3 strings which someFunc packages up into a dynamic array of char[] - and on the plus side it doesn't allocate any memory. If you want to use the args array after someFunc returns you can just .dup it.

-Ben