Consume an entire range

Brad Anderson eco at gnuk.net
Thu May 30 10:58:45 PDT 2013


On Thursday, 30 May 2013 at 11:38:58 UTC, bearophile wrote:
> Brad Anderson:
>
>> 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.
>
> Maybe here it's better to work on lines. Alternatively I don't 
> know if you can read the whole input there.

I posted a version that worked on lines instead.  I was having 
trouble but the trouble was actually the same problem I was 
having with the joined version (my map wasn't being consumed).

>
> It's usually better to give only pure functions to filter/map, 
> because in Bugzilla I've shown those higher order functions 
> don't work well otherwise.
>

Have any links?  I considered using sort and uniq to avoid the 
closure around dic but then the order would be different and I 
wanted to keep it using a similar technique to the original.

> So I prefer a terminal function that takes an impure function 
> and returns nothing, something like:
>
> ...
> .filter!(w => !w.empty && w !in dic)
> .forEach!((w) { writeln(dic[w.idup] = dic.length, '\t', w); });
>

Is forEach real?  I sought it out because it'd be a better fit 
but came up empty (it's not in std.range or std.algorithm).

>
> Bye,
> bearophile


More information about the Digitalmars-d-learn mailing list