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.)