digitalmars.D.learn - Consume an entire range
- Brad Anderson (3/3) May 29 2013 Is there a simple way to consume a range apart from
- Brad Anderson (4/7) May 29 2013 Obviously I could just popFront. To be more clear, I want
- Jonathan M Davis (7/15) May 29 2013 If you specifically want to iterate over it, then I think that you need ...
- Brad Anderson (50/70) May 29 2013 There was a filter in the change so I had no length. The tailing
- Brad Anderson (10/26) May 29 2013 Ok, I guess it's not that weird after all:
- bearophile (13/28) May 30 2013 Maybe here it's better to work on lines. Alternatively I don't
- Brad Anderson (9/40) May 30 2013 I posted a version that worked on lines instead. I was having
- Jonathan M Davis (3/5) May 30 2013 No. The normal thing would be to just use an actual foreach loop.
- bearophile (5/7) May 30 2013 It's just an idea.
- Diggory (2/9) May 29 2013 There's "walkLength"?
- Jonathan M Davis (5/16) May 29 2013 Ah, I should have thought of that, though that won't work if the range d...
- Diggory (3/23) May 29 2013 Do you think it would be worth adding a "consume" method to
- Brad Anderson (4/14) May 29 2013 I tried that. There is an isInputRange && !isInfinite template
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.
May 29 2013
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.
May 29 2013
On Thursday, May 30, 2013 05:53:02 Brad Anderson wrote:On Thursday, 30 May 2013 at 03:50:52 UTC, Brad Anderson wrote: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 DavisIs 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.
May 29 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: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-chOn Thursday, 30 May 2013 at 03:50:52 UTC, Brad Anderson wrote: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 DavisIs 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.
May 29 2013
On Thursday, 30 May 2013 at 04:30:11 UTC, Brad Anderson wrote:[snip] 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.Ok, I guess it's not that weird after all: void main() { size_t[string] dic; stdin.byLine .map!(l => l.splitter(' ') .filter!(w => !w.empty && w !in dic) .map!(w => writeln(dic[w.idup] = dic.length, '\t', w)).eat).eat; }
May 29 2013
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. 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. 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); }); Bye, bearophile
May 30 2013
On Thursday, 30 May 2013 at 11:38:58 UTC, bearophile wrote:Brad Anderson: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).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.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
May 30 2013
On Thursday, May 30, 2013 19:58:45 Brad Anderson wrote: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).No. The normal thing would be to just use an actual foreach loop. - Jonathan M Davis
May 30 2013
Brad Anderson:Have any links?http://d.puremagic.com/issues/show_bug.cgi?id=9674Is forEach real?It's just an idea. Bye, bearophile
May 30 2013
On Thursday, 30 May 2013 at 03:53:06 UTC, Brad Anderson wrote:On Thursday, 30 May 2013 at 03:50:52 UTC, Brad Anderson wrote:There's "walkLength"?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.
May 29 2013
On Thursday, May 30, 2013 06:12:51 Diggory wrote:On Thursday, 30 May 2013 at 03:53:06 UTC, Brad Anderson wrote:Ah, I should have thought of that, though that won't work if the range defines length. Of course, if it defines length, you can always use popFrontN with length. - Jonathan M DavisOn Thursday, 30 May 2013 at 03:50:52 UTC, Brad Anderson wrote:There's "walkLength"?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.
May 29 2013
On Thursday, 30 May 2013 at 04:18:14 UTC, Jonathan M Davis wrote:On Thursday, May 30, 2013 06:12:51 Diggory wrote:Do you think it would be worth adding a "consume" method to std.range or std.algorithm?On Thursday, 30 May 2013 at 03:53:06 UTC, Brad Anderson wrote:Ah, I should have thought of that, though that won't work if the range defines length. Of course, if it defines length, you can always use popFrontN with length. - Jonathan M DavisOn Thursday, 30 May 2013 at 03:50:52 UTC, Brad Anderson wrote:There's "walkLength"?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.
May 29 2013
On Thursday, 30 May 2013 at 04:12:56 UTC, Diggory wrote:On Thursday, 30 May 2013 at 03:53:06 UTC, Brad Anderson wrote:I tried that. There is an isInputRange && !isInfinite template constraint but I don't see how my stuff didn't meet that requirement.On Thursday, 30 May 2013 at 03:50:52 UTC, Brad Anderson wrote:There's "walkLength"?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.
May 29 2013