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.

Reply via email to