Thread overview
non-typesafe variadic lazy arguments
Feb 01, 2008
Regan Heath
January 28, 2008
I'm sure this has been asked before, but I can't remember the answer.

How does one create a function that takes non-typed variadic arguments?

Essentially, what I want is for this to work:

void f(lazy ...);

The current spec allows for typed variadic lazy functions i.e.:

void f(char[] delegate()[] dg ...); // every arg has to be a char[]

But if I want any type to be passed in, there doesn't seem to be a way to do it, as there is no builtin type that any type can be casted to implicitly (or is there?).

If I want to evaluate the variadic args lazily, I can use a level of indirection:

char[] evalOnCondition(bool condition, lazy char[] result)
{
   if(condition) writefln(result);
}

variadicF(char[] buffer, ...){...}

char[400] buf;
evalOnCondition(loops==5, variadicF(buf, "inloop", 5));

But what I really want to do is intercept the variadic function call.  I want to provide a function that allows you to call evalOnCondition and variadicF without a buffer and without allocating it from the heap:

variadicEvalOnCondition(bool condition, lazy ...)
{
  char[400] buf;
  if(condition)
    writefln(variadicF(buf, _argptr, _arguments)); // doesn't eval ... until
here
}

Any ideas how this can be done?

-Steve


February 01, 2008
Does nobody have any insight on this? :(

-Steve

"Steven Schveighoffer" wrote
> I'm sure this has been asked before, but I can't remember the answer.
>
> How does one create a function that takes non-typed variadic arguments?
>
> Essentially, what I want is for this to work:
>
> void f(lazy ...);
>
> The current spec allows for typed variadic lazy functions i.e.:
>
> void f(char[] delegate()[] dg ...); // every arg has to be a char[]
>
> But if I want any type to be passed in, there doesn't seem to be a way to do it, as there is no builtin type that any type can be casted to implicitly (or is there?).
>
> If I want to evaluate the variadic args lazily, I can use a level of indirection:
>
> char[] evalOnCondition(bool condition, lazy char[] result)
> {
>   if(condition) writefln(result);
> }
>
> variadicF(char[] buffer, ...){...}
>
> char[400] buf;
> evalOnCondition(loops==5, variadicF(buf, "inloop", 5));
>
> But what I really want to do is intercept the variadic function call.  I want to provide a function that allows you to call evalOnCondition and variadicF without a buffer and without allocating it from the heap:
>
> variadicEvalOnCondition(bool condition, lazy ...)
> {
>  char[400] buf;
>  if(condition)
>    writefln(variadicF(buf, _argptr, _arguments)); // doesn't eval ...
> until here
> }
>
> Any ideas how this can be done?
>
> -Steve


February 01, 2008
Does this help:

module lazy_any;

import std.thread;
import std.stdio;
import std.c.time;
import std.c.string;
import std.string;

void call(R, U...)(bool condition, R delegate(U) dg, U args)
{
	if (condition)
		writefln(dg(args));
}

void main(string[] args)
{
	string bob(int i, string s, float f)
	{
		return format("%s, %s, %s", i, s, f);
	}
	
	call(true,  &bob, 1, "test1".idup, 5.2f);
	call(false, &bob, 2, "test2".idup, 6.3f);
	call(true,  &bob, 3, "test3".idup, 7.4f);
}
February 04, 2008
"Regan Heath" wrote
> Does this help:
>
> module lazy_any;
>
> import std.thread;
> import std.stdio;
> import std.c.time;
> import std.c.string;
> import std.string;
>
> void call(R, U...)(bool condition, R delegate(U) dg, U args)
> {
> if (condition)
> writefln(dg(args));
> }
>
> void main(string[] args)
> {
> string bob(int i, string s, float f)
> {
> return format("%s, %s, %s", i, s, f);
> }
>
> call(true,  &bob, 1, "test1".idup, 5.2f);
> call(false, &bob, 2, "test2".idup, 6.3f);
> call(true,  &bob, 3, "test3".idup, 7.4f);
> }

I definitely learned something here, but unfortunately, this doesn't solve the problem.  What I want is for the tuple to be converted to delegates just like lazy converts arguments to delegates.

To demonstrate my issue, I think this would still evaluate f:


string f(string x, string y)
{
  return x ~ y;
}

call(false, &bob, 1, f("test", "1"), 5.2f);

What I want is a way so that f("test", "1") is not evaluated unless needed.

-Steve


February 04, 2008
"Steven Schveighoffer" wrote
> "Regan Heath" wrote
>> Does this help:
>>
>> module lazy_any;
>>
>> import std.thread;
>> import std.stdio;
>> import std.c.time;
>> import std.c.string;
>> import std.string;
>>
>> void call(R, U...)(bool condition, R delegate(U) dg, U args)
>> {
>> if (condition)
>> writefln(dg(args));
>> }
>>
>> void main(string[] args)
>> {
>> string bob(int i, string s, float f)
>> {
>> return format("%s, %s, %s", i, s, f);
>> }
>>
>> call(true,  &bob, 1, "test1".idup, 5.2f);
>> call(false, &bob, 2, "test2".idup, 6.3f);
>> call(true,  &bob, 3, "test3".idup, 7.4f);
>> }
>
> I definitely learned something here, but unfortunately, this doesn't solve the problem.  What I want is for the tuple to be converted to delegates just like lazy converts arguments to delegates.
>
> To demonstrate my issue, I think this would still evaluate f:
>
>
> string f(string x, string y)
> {
>  return x ~ y;
> }
>
> call(false, &bob, 1, f("test", "1"), 5.2f);
>
> What I want is a way so that f("test", "1") is not evaluated unless needed.
>
> -Steve
>

However, this does work:

void call(R, U...)(bool condition, R delegate(U) dg, lazy U args)
{
if (condition)
writefln(dg(args));
}

Thanks for the help Regan!!! :)

-Steve


February 05, 2008
"Steven Schveighoffer" wrote
> However, this does work:
>
> void call(R, U...)(bool condition, R delegate(U) dg, lazy U args)
> {
> if (condition)
> writefln(dg(args));
> }
>
> Thanks for the help Regan!!! :)
>
> -Steve

ugh! it almost works :)  The issue is with lazy args and string/array literals.

If you do this:

call(true, &bob, "hello");

The compiler complains because it can't create a delegate function that returns a char[5u].  Functions cannot return a static array, so this seems rather silly (i.e. if you are lazily evaluating a string constant, there is no penalty for returning a char[] instead of a char[5u]).  I'm going to file it as a bug, but if this gets fixed, everything will be good!

-Steve