www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - non-typesafe variadic lazy arguments

reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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 
Jan 28 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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 

Feb 01 2008
parent reply Regan Heath <regan netmail.co.nz> writes:
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);
}
Feb 01 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"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
Feb 04 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"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
Feb 04 2008
parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"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
Feb 05 2008