it's time to change how things are printed

Nick Sabalausky a at a.a
Thu Nov 18 07:44:00 PST 2010


"Steven Schveighoffer" <schveiguy at yahoo.com> wrote in message 
news:op.vmdglth8eav7ka at localhost.localdomain...
>A recent bug report reminded me of how horrible D is at printing custom 
>types.
>
> Consider a container type that contains 1000 elements, such as a linked 
> list.  If you print this type, you would expect to get a printout similar 
> to an array, i.e.:
>
> [ 1 2 3 4 5 ... 1000 ]
>
> If you do this:
>
> writeln(mylist);
>
> then what happens is, writeln calls mylist.toString(), and prints that 
> string.
>
> But inside mylist.toString, it likely does things like elem[0].toString() 
> and concatenates all these together.  This results in at least 1000 + 1 
> heap allocations, to go along with 1000 appends,  to create a string that 
> will be sent to an output stream and *discarded*.
>
> So the seemingly innocuous line writeln(mylist) is like attaching a boat 
> anchor to your code performance.
>
> There is a better way, as demonstrated by BigInt (whose author refuses to 
> implement toString()):
>
> void toString(scope void delegate(scope const(char)[] data), string format 
> = null)
>
> What does this do?  Well, now, writeln can define a delegate that takes a 
> string and sends it to an output stream.  Now, there is no copying of 
> data, no heap allocations, and no need to concatenate anything together! 
> Not only that, but it can be given an optional format specifier to control 
> output when writefln is used.  Let's see how a linked list would implement 
> this function (ignoring format for now):
>
> void toString(scope void delegate(scope const(char)[] data) sink, string 
> format = null)
> {
>    sink("[");
>    foreach(elem; this)
>    {
>       sink(" ");
>       elem.toString(sink);
>    }
>    sink(" ]");
> }
>
> It looks just about as simple as the equivalent function that would 
> currently be necessary, except you have *no* heap allocations, there is a 
> possibility for formatting, and D will be that much better performing. 
> Note that using a delegate allows much more natural code which requires 
> recursion.
>
> Should we create a DIP for this?  I'll volunteer to spearhead the effort 
> if people are on board.
>

I like it, *provided that* there's a quick-and-easy way to just get a string 
when that's all you want. At the very least there should be a standard sink 
function that's a default argument to toString that just simply builds a 
string. What we definitely *don't* want is for the user to ever have to 
write their own sink delegate just to get a string (which I've had to do 
with Tango on occasion).




More information about the Digitalmars-d mailing list