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

Reply via email to