March 25, 2014
I'm not sure what I'm doing wrong... the following code prints nothing:

void main()
{
    import std.stdio, std.range;
	
    string str = "asdf";
    auto sink = new dchar[](str.length);
    auto fun = (dchar c) { sink.put(c); };
    foreach (dchar c; str)
    {
        fun(c);
    }
    writeln(sink);
}

If I print sink's length inside the foreach loop, its length is reduced by 1 each step, until it's 0. That explains why nothing is being printed, but why is put altering the length of the array?
March 25, 2014
On 03/24/2014 07:42 PM, Meta wrote:

> I'm not sure what I'm doing wrong... the following code prints nothing:
>
> void main()
> {
>      import std.stdio, std.range;
>
>      string str = "asdf";
>      auto sink = new dchar[](str.length);
>      auto fun = (dchar c) { sink.put(c); };
>      foreach (dchar c; str)
>      {
>          fun(c);
>      }
>      writeln(sink);
> }
>
> If I print sink's length inside the foreach loop, its length is reduced
> by 1 each step, until it's 0. That explains why nothing is being
> printed, but why is put altering the length of the array?

Very many things can be output ranges depending on what operations they support:

  http://dlang.org/phobos/std_range.html#.put

sink above is a slice, matching "if R defines put, r.front = e if r is an input range (followed by r.popFront())" in the above document. That's popFront() in that excerpt that is causing the loss of element here.

I have a more detailed explanation of this under the "Using slices as OutputRange" section in the following chapter:

  http://ddili.org/ders/d.en/ranges.html

So, one of the solutions here is to use a surrogate slice instead:

    auto sinkSurrogate = sink;
    auto fun = (dchar c) { sinkSurrogate.put(c); };

Now, sinkSurrogate will lose elements and sink will still be usable.

Ali