digitalmars.D - Empowering foreach with in-place iteration
- Janice Caron (49/49) Sep 09 2007 There are some things that iterators can do that foreach can't. I
- Daniel Keep (29/29) Sep 09 2007 Again, this would be tricky to do. Since the body of a loop is a
- BCS (7/30) Sep 09 2007 The iterate could be done by putting a pointer (and most of the local va...
There are some things that iterators can do that foreach can't. I /don't/ want to add iterators to D. Instead, I'd like to see foreach enhanced, so that it can do the things it currently can't. Here's my second example. string unescape(string s) { string r; for (int i=0; i<s.length; ++i) { if (s[i] == '\') { ++i; if (i == s.length) break; r ~= f(s[i]); } else { r ~= s[i]; } } return r; } How much nicer it would be to be able to write this as: string unescape(string s) { string r; for (char c; s) { if c == '\') { iterate(s); /* advances one step through s; modifies c */ r ~= f(c); } else { r ~= c; } } return r; } I'd also like to be able to advance by n steps, not necessarily just one. That could be done with something like iterate(s,n). For that matter, I'd also like to go backwards, so it would be great if n could be negative. Of course there are some subtleties to consider. What happens if we reach beyond the end of the array (or the beginning, if we go backwards)? Is it sufficient to act like break, as in my example above? Or should that throw an exception? I don't really mind which behavior is chosen. Either way, I'd still like the feature.
Sep 09 2007
Again, this would be tricky to do. Since the body of a loop is a function, you can't call into it at a specific place. It's also not something that crops up very often. Perhaps a better alternative might be to try for generators; that (possibly combined with some kind of special aggregate declaration) might solve the problem. string unescape(string s) { string r; foreach( c ; aggregate = s.iter ) { if c == '\') { c = aggregate.next; r ~= f(c); } else { r ~= c; } } return r; } As a bonus, this would make writing custom aggregates much easier, and possibly allow for easier implementation of lockstep iteration. On a side note, my PullDOM implementation actually allows for exactly this sort of behaviour, so it's certainly something you can do right now; you just need to construct the aggregate appropriately. -- Daniel
Sep 09 2007
Reply to Janice,There are some things that iterators can do that foreach can't. I /don't/ want to add iterators to D. Instead, I'd like to see foreach enhanced, so that it can do the things it currently can't. Here's my second example. string unescape(string s) { string r; foreach (char c; s) { if c == '\') { iterate(s); /* advances one step through s; modifies c */ r ~= f(c); } else { r ~= c; } } return r; }The iterate could be done by putting a pointer (and most of the local variables) in the stack frame outside the foreach and having the iterate actually be a "store next op in ptr, return" and then placing a goto ptr at the start of the function. this would let the function return and resume at the same point on the next call (this is something like a generator I think). languages support needed big time.
Sep 09 2007