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

Reply via email to