Can't understand the application of delegates in toString() functions

Mathias Lang via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Nov 7 08:37:50 PST 2016


On Monday, 7 November 2016 at 16:22:17 UTC, Heisenberg wrote:
> Hi there. I'm currently following Ali Çehreli's "Programming in 
> D" book and I can't seem to be able to wrap my head around the 
> of delegates in the toString() functions..
>
> http://ddili.org/ders/d.en/lambda.html
> (Bottom of the page)
>
>
> Why? How can a delegate which returns nothing be used as an 
> array which is going to be printed on the screen? And just how 
> is it printed? The Documentation didn't make it much clearer.. 
> the 'sink' is supposed to be the 'writer', isn't it? So what 
> does it do? The arguments get interpreted and formatted into 
> the string, but what happens after that?
>
> P.S. I've just checked the book, it doesn't seem to be 
> explained anywhere properly (the way formattedRead is)
> P.P.S. I'm following the PDF version of the book

When you ask for a string (or more generally, an array), you put 
a specific construct on the way the data should be. For starters, 
the items have to be contiguous in memory. But most of the time, 
they aren't, and you end up allocating memory to put them 
contiguously.

A sink is a method to work around that problem. A simple example 
would be:

```
import std.stdio;

void main ()
{
    // A delegate that write to stdout
    auto dg = (const(char)[] v) { write(v); }
    ColoredPoint p;
    p.toString(dg);
    write("\n");
}
```

With this definition, every time `ColoredPoint` will want to 
output a chunk of data, it will call the delegate, which will 
print to stdout. When the function returns, we now all chunks 
have been appended, and we complete the line with a \n, flushing 
the output.

This is great to write memory-friendly algorithm:

```
void main ()
{
    AppendBuffer!char myBuffer;
    auto dg = (const(char)[] v) { myBuffer ~= v; }
    ColoredPoint p;
    p.toString(dg);
    // Now we can use myBuffer.data
}
```

With this example, you can see that, by just forwarding chunks to 
the delegate, we're able to let the caller to decide of the 
memory strategy to use. It can be plain GC allocation, it can be 
using `malloc` / `realloc`, it can use a static array and only 
aggregate up to a certain size, etc...


More information about the Digitalmars-d-learn mailing list