digitalmars.D.learn - how to handle void arguments in generic programming ?
- Timothee Cour (9/9) Nov 10 2013 The code snippet below doesn't work. Is there a way to make it work?
- Dicebot (16/26) Nov 11 2013 Considering "cannot have parameters of type void" error, I doubt
- Timon Gehr (33/42) Nov 11 2013 import std.stdio;
- Dicebot (2/3) Nov 11 2013 Whoa, one can apply attributes to variadic argument list? Yummy!
- Timon Gehr (45/46) Nov 11 2013 This was a little too quick. It does not work too well since if the last...
The code snippet below doesn't work. Is there a way to make it work? import std.stdio; void main(){ writelnIfNonVoid(writeln("ok")); } void writelnIfNonVoid(T...)(T a){ static if(T.length) writeln(a); }
Nov 10 2013
On Monday, 11 November 2013 at 03:52:16 UTC, Timothee Cour wrote:The code snippet below doesn't work. Is there a way to make it work? import std.stdio; void main(){ writelnIfNonVoid(writeln("ok")); } void writelnIfNonVoid(T...)(T a){ static if(T.length) writeln(a); }Considering "cannot have parameters of type void" error, I doubt it. Using lambda can do as workaround though (returning void is legal): import std.stdio; import std.traits; void main() { writelnIfNonVoid(() { writeln("ok"); }); } void writelnIfNonVoid(T)(T f) if (isSomeFunction!T) { static if (!is(ReturnType!T == void)) writeln(a); }
Nov 11 2013
On 11/11/2013 04:52 AM, Timothee Cour wrote:The code snippet below doesn't work. Is there a way to make it work? import std.stdio; void main(){ writelnIfNonVoid(writeln("ok")); } void writelnIfNonVoid(T...)(T a){ static if(T.length) writeln(a); }import std.stdio; void main(){ writelnIfNonVoid(writeln("ok")); } void writelnIfNonVoid(T...)(lazy T a){ static if(T.length){ static if(is(T[0]==void)) a[0]; else write(a[0]); static if(T.length==1) writeln(); else writelnIfNonVoid(a[1..$]); } } Or, if you care about evaluation order and locking stdout: import std.stdio; void main(){ writelnIfNonVoid(writeln("ok")); } void writelnIfNonVoid(T...)(lazy T a){ import std.range, std.algorithm, std.conv; mixin({ string[] indices=iota(a.length).map!(i=>"a["~to!string(i)~"]").array~"cast(void)0"; string r; foreach(i,t;T){ if(is(t==void)) indices[i+1]="("~indices[i]~","~indices[i+1]~")"; else r~=indices[i]~","; } if(r.length) r="writeln("~r~");"; return r~indices[$-1]~";"; }()); }
Nov 11 2013
On Monday, 11 November 2013 at 13:06:14 UTC, Timon Gehr wrote:void writelnIfNonVoid(T...)(lazy T a){Whoa, one can apply attributes to variadic argument list? Yummy!
Nov 11 2013
On 11/11/2013 02:06 PM, Timon Gehr wrote:Or, if you care about evaluation order and locking stdout:This was a little too quick. It does not work too well since if the last parameter is of type void, the newline is emitted before the trailing arguments of type void are evaluated, which may not be exactly what you wanted. The following should work, however DMD does not properly support the (exp,Seq!()) construct, so it won't compile in this case: alias Seq(T...)=T; void writelnIfNonVoid(T...)(lazy T a){ import std.range, std.algorithm, std.conv; mixin({ string[] indices=iota(a.length).map!(i=>"a["~to!string(i)~"]").array~"Seq!()"; string r; foreach(i,t;T){ if(is(t==void)) indices[i+1]="("~indices[i]~","~indices[i+1]~")"; else r~=indices[i]~","; } if(r.length) return "writeln("~r~indices[$-1]~");"; return indices[$-1]!="Seq!()"?indices[$-1]~";":""; }()); } This could be worked around as follows, but then you might get more postblit invocations than in the previous version: import std.stdio; void main(){ writelnIfNonVoid("123",writeln("ok")); } void writelnIfNonVoid(T...)(lazy T a){ import std.conv; static if(T.length) mixin({ string r,args; foreach(i,t;T){ if(!is(t==void)){ r~="auto r_"~to!string(i)~"="; args~="r_"~to!string(i)~","; } r~="a["~to!string(i)~"];"; } return r~"writeln("~args~");"; }()); } (Not sure what you intended the exact rules for emmiting a line feed character to be.)
Nov 11 2013