Consume an entire range
Brad Anderson
eco at gnuk.net
Wed May 29 21:30:08 PDT 2013
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
More information about the Digitalmars-d-learn
mailing list