On Thursday, 30 May 2013 at 04:00:39 UTC, Jonathan M Davis wrote:
On Thursday, May 30, 2013 05:53:02 Brad Anderson wrote:
On Thursday, 30 May 2013 at 03:50:52 UTC, Brad Anderson wrote:
> Is there a simple way to consume a range apart from
> std.array.array? I don't need to result of the range stored > in
> an array, I just need a lazy map to evaluate completely.

Obviously I could just popFront.  To be more clear, I want
something like eat() or consume() or exhaust() that I can tack on
the end of my chained algorithm calls.

If you specifically want to iterate over it, then I think that you need to repeatedly call popFront (or callPopFrontN if it hasLength). However, if what
you want is for the resultant range to be empty, you can use
std.range.takeNone. If it can, it'll return the same range type as the
original, and if it can't, it'll return takeExactly(range, 0).

- Jonathan M Davis

There was a filter in the change so I had no length. The tailing map had a void element type which mean foreach didn't work on it.

I ended up with:

void eat(R)(R r) { while(!r.empty) { r.front; r.popFront(); } }

I was actually just playing around reimplementing Andrei's example from his InformIT article[1] using std.algorithm and friends. It went from:

import std.stdio, std.string;

void main() {
   uint[string] dic;
   foreach (line; stdin.byLine) {
      // Break sentence into words
      string[] words = split(strip(line));
      // Add each word in the sentence to the vocabulary
      foreach (word; words) {
         if (word in dic) continue; // nothing to do
         uint newID = dic.length;
         dic[word] = newID;
         writeln(newID, '\t', word);
      }
   }
}

to:

import std.stdio, std.algorithm, std.array;

void eat(R)(R r) { while(!r.empty) { r.front; r.popFront; } }

void main() {
   size_t[dstring] dic;
   stdin.byLine
           .joiner(" ")
           .array
           .splitter(' ')
           .filter!(w => !w.empty && w !in dic)
           .map!(w => writeln(dic[w.idup] = dic.length, '\t', w))
           .eat;
}

I would have prefered to not use joiner() but working with ranges of ranges of ranges (splitter() on each line) got a bit weird and confusing.

splitter() needed array slicing and length which joiner() doesn't have so I had to use array(). I was confused about why I was suddenly getting dchar[] out the other end but found the StackOverflow question [2] in which you explain why joiner does that (you really kick ass at answering StackOverflow questions, Jonathan). Having a variant of splitter that ignores empty tokens would be nice to have too.

1. http://www.informit.com/articles/article.aspx?p=1381876&seqNum=4 2. http://stackoverflow.com/questions/12288465/std-algorithm-joinerstring-string-why-result-elements-are-dchar-and-not-ch

Reply via email to