digitalmars.D.learn - An input range iteration question
- ref2401 (29/29) Apr 08 2015 If Iterator is a struct then Iterator.input won't be adjusted
- Adam D. Ruppe (10/10) Apr 08 2015 A struct is copied when you pass it to foreach, so it iterates
If Iterator is a struct then Iterator.input won't be adjusted properly when the foreach loop ends. Iterator.input still holds "abcde" value. If i mark Iterator as class then Iterator.input will be an empty string after the foreach loop. Could anyone explain me the difference please? Thank you. struct Iterator { string input; this(string input) { this.input = input; } bool empty() { return input.empty; } dchar front() { return input.front; } void popFront() { if (empty) { return; } input.popFront(); writeln("(iterator.popFront)", input); } } void main(string[] args) { Iterator iterator = Iterator("abcde"); foreach (dchar c; iterator) { writefln("%s", c); } writefln("(the end): %s", iterator.input); }
Apr 08 2015
A struct is copied when you pass it to foreach, so it iterates over the copy leaving the original the same. A class is referenced by foreach, so the original is affected by it. This is one reason why separating containers from the ranges/iterators that go over them is helpful: the iterator looks at, but doesn't modify the container. When it is done as a separate struct, this typically works fairly easily (unless the act of iterating the container is destructive, like reading from a pipe...)
Apr 08 2015