writeln if not empty

Timothee Cour thelastmammoth at gmail.com
Mon Mar 10 22:37:14 PDT 2014


On Mon, Mar 10, 2014 at 9:14 PM, Jonathan M Davis <jmdavisProg at gmx.com>wrote:

> On Monday, March 10, 2014 21:50:25 Nick Sabalausky wrote:
> > On 3/10/2014 9:24 PM, Timothee Cour wrote:
> > > Is there a way to do the following lazily:
> > >
> > > writelnIfNotEmpty(T)(T a){
> > > auto b=text(a);
> > > if(b.length)
> > >
> > >    writeln(b);
> > >
> > > }
> > >
> > > ie, without using std.conv.text (which needlessly computes an
> intermediate
> > > string, which could be quite large) or launching a separate process ?
> > >
> > > writelnIfNotEmpty(""); //doesn't print new line
> > > writelnIfNotEmpty("a"); //prints "a\n"
> >
> > Sounds like what you need is a version of to!string() or text() that
> > takes an output sink. Taking a look at std.conv, I'm kinda surprised I
> > don't see one :/
>
> std.format.formattedWrite will do the equivalent of writef to an output
> range,
> though I'm not sure that that will really do what the OP wants, since it
> would
> still have to write the result to an output range even if it were empty,
> and
> odds are that the output range would be something on the heap anyway (e.g.
> Appender is technically on the stack, but it's contents are on the heap),
> making it so that it probably doesn't help much in this case.
>
> Though to be honest, I'm not quite sure why writelnIfNotEmpty would be very
> useful unless what's being passed in would result in the empty string, and
> I
> would think that that would almost always be detectable (the one exception
> being user-defined types whose toString results in an empty string).
> Something
> as simple as
>
> void writelnIfNotEmpty(T)(T a)
> {
>     static if(isInputRange!T)
>     {
>         if(!a.empty)
>             writeln(a);
>     }
>     else
>         writeln(a);
> }
>
> would then cover most cases - the one exception being toStrings which can
> result in empty. And if that's a concern, then something like
>
>     else static if(is(T == struct) || is(T == class))
>     {
>         auto b = to!string(a);
>         if(b.length)
>             writeln(b);
>     }
>
> should take care of the toString case. It doesn't avoid creating an
> intermediate string, but unless the toString takes an output range, it's
> always going to allocate anyway, and if it does take an output range, once
> again, you'd need one which somehow avoided allocating altogether, which
> isn't
> particularly likely.
>
> Alternatively, you could just assume that no toString will result in the
> empty
> string, as it's probably pretty rare that it would, but I'm not sure that
> that
> would actually save you any overhead except in the case where the toString
> takes an output range (since otherwise, it'll allocate a new string
> regardless), but toStrings which take output ranges are fairly uncommon at
> this point.
>
> - Jonathan M Davis
>


Thanks,
that indeed works in many cases but there are still others (eg what if
empty() prints, say in debug mode: writelnIfNotEmpty would not print the
debug information even though writeln() would execute that debug code and
print something).

I was wondering whether there would be a robust way that would check
whether anything was written to stdout (eg via accessing raw file pointer/C
lib), eg something like that :

void writelnIfNotEmpty(T)(T a){
auto file_pos=get_filepos(stdin);
write(a);
if(get_filepos(stdin)!=file_pos)
writeln;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-learn/attachments/20140310/6ec48dde/attachment.html>


More information about the Digitalmars-d-learn mailing list