On 8/24/21 4:36 AM, frame wrote:
Consider a simple input range that can be iterated with empty(), front()
and popFront(). That is comfortable to use with foreach() but what if
the foreach loop will be cancelled? If a range isn't depleted yet and
continued it will supply the same data twice on front() in the next use
of foreach().
For some reason, foreach() does not call popFront() on a break or
continue statement.
continue calls `popFront`. break does not.
There is no way to detect it except the range itself
tracks its status and does an implicit popFront() if needed - but then
this whole interface is some kind of useless.
You can call `popFront` if you need to after the loop, or just before
the break. I have to say, the term "useless" does not even come close to
describing ranges using foreach in my experience.
There is opApply() on the other hand that is designed for foreach() and
informs via non-0-result if the loop is cancelled - but this means that
every range must implement it if the range should work in foreach()
correctly?
`opApply` has to return different values because it needs you to pass
through its instructions to the compiler-generated code. The compiler
has written the delegate to return the message, and so you need to pass
through that information. The non-zero result is significant, not just
non-zero. For instance, if you end with a `break somelabel;` statement,
it has to know which label to go to.
The correct behavior for `opApply` should be, if the delegate returns
non-zero, return that value immediately. It should not be doing anything
else. Would you be happy with a `break somelabel;` actually triggering
output? What if it just continued the loop instead? You don't get to
decide what happens at that point, you are acting as the compiler.
This is very inconsistent. Either foreach() should deny usage of ranges
that have no opApply() method or there should be a reset() or cancel()
method in the interfaces that may be called by foreach() if they are
implemented.
How do you handle that issue? Are your ranges designed to have this bug
or do you implement opApply() always?
It's not a bug. So there is no need to "handle" it.
The pattern of using a for(each) loop to align certain things occurs all
the time in code. Imagine a loop that is looking for a certain line in a
file, and breaks when the line is there. Would you really want the
compiler to unhelpfully throw away that line for you?
And if that is what you want, put `popFront` in the loop before you
exit. You can't "unpopFront" something, so this provides the most
flexibility.
-Steve