writeln wipes contents of variables ?

Rikki Cattermole via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Jan 21 05:15:46 PST 2016


On 22/01/16 2:11 AM, W.J. wrote:
> Hi everybody!
>
> I'm new to D and trying to wrap my head around ranges.
>
> For a start I'm trying to take a input string and transform it, group
> it, etc.
> After each step I inspect the result.
> It works fine until step 3 where all of a sudden, after write(ln)ing the
> result, "step3" holds an array of empty arrays.
> What gives? Program and output are attached below.
>
> My question is why are "step3"'s contents before and after the writeln
> (1) different?
> If I remove this line at (1) the foreach loops print the contents as I'd
> expect and the following writeln (2) prints the contents as expected, too.
> However the writeln (3) prints empty arrays again.
> I don't understand this behavior and I'd really like to know what's
> going on.
>
> Your help and time is much appreciated!
>
> I'm using an unmodified local build of dmd, druntime, and phobos from
> github updated and recompiled today.
>
> [code]
> import std.range;
> import std.stdio;
> import std.algorithm;
>
> void main() {
>    string test = "@\r  node1\n    nodea\r\n    key:val\n\n node2\n
> nodea\n";
>    writeln(test);
>    writeln("---");
>
>    auto step1 = test.replace("\r\n", "\n")
>                  .replace("  ", "\t")
>                  .splitter!"a == 10 || a == 13"()
>                  ;
>    writeln("Step 1:", step1);
>    writeln("---");
>    writeln("  type: ", typeid(step1));
>    writeln("---");
>
>    import std.typecons: Tuple;
>    string[][] step2;
>    foreach(a; step1) {
>      auto e = findSplitAfter(a, "\t").array;
>      step2 ~= e;
>    }
>    writeln("Step 2:", step2);
>    writeln("---");
>    writeln("  type: ", typeid(step2));
>    writeln("---");
>
>    auto step3 = step2.chunkBy!((a,b) => a[0]==b[0]).array;
>    writeln("Step 3:", step3); // (1)
>    writeln("---");
>    writeln("  type: ", typeid(step3));
>    writeln("-+-");
>
>    foreach(x; step3) {
>      writeln("x:",typeid(x),x);
>      foreach(y; x)
>        writeln("  y:",typeid(y),y);
>    }
>    writeln("--",step3); // (2)
>    writeln("--",step3); // (3)
>    writeln("the end");
> }
> [/code]
>
> Output:
> [code]
>    node1
>      nodea
>      key:val
>
>    node2
>      nodea
>
> ---
> Step 1:["@", "\tnode1", "\t\tnodea", "\t\tkey:val", "", "\tnode2",
> "\t\tnodea", ""]
> ---
>    type: std.algorithm.iteration.SplitterResult!(unaryFun,
> string).SplitterResult
> ---
> Step 2:[["", "@"], ["\t", "node1"], ["\t", "\tnodea"], ["\t",
> "\tkey:val"], ["", ""], ["\t", "node2"], ["\t", "\tnodea"], ["", ""]]
> ---
>    type: immutable(char)[][][]
> ---
> Step 3:[[["", "@"]], [["\t", "node1"], ["\t", "\tnodea"], ["\t",
> "\tkey:val"]], [["", ""]], [["\t", "node2"], ["\t", "\tnodea"]], [["",
> ""]]]
> ---
>    type: app.main.ChunkByImpl!(__lambda1, string[][]).ChunkByImpl.Group[]
> -+-
> x:app.main.ChunkByImpl!(__lambda1, string[][]).ChunkByImpl.Group[]
> x:app.main.ChunkByImpl!(__lambda1, string[][]).ChunkByImpl.Group[]
> x:app.main.ChunkByImpl!(__lambda1, string[][]).ChunkByImpl.Group[]
> x:app.main.ChunkByImpl!(__lambda1, string[][]).ChunkByImpl.Group[]
> x:app.main.ChunkByImpl!(__lambda1, string[][]).ChunkByImpl.Group[]
> --[[], [], [], [], []]
> the end
> [/code]

Ok so input ranges.
An input range is a little bit like an iterator (if you know what that is).

When an input range has been read fully, it is empty aka no longer has 
any values associated with it.

writeln, reads an input range fully (since you can't ask for what is 
next without removing the current item) and outputs each entry.

So yes, writeln will remove all entries from an input range.
Note however it will not do this for arrays since you can read anywhere 
within them.


More information about the Digitalmars-d-learn mailing list