On Tuesday, 24 August 2021 at 21:15:02 UTC, Steven Schveighoffer wrote:

If you have a for loop:

```d
int i;
for(i = 0; i < someArr.length; ++i)
{
   if(someArr[i] == desiredValue) break;
}
```

You are saying, "compiler, please execute the `++i` when I break from the loop because I already processed that one". How can that be expected? I would *never* expect that. When I break, it means "stop the loop, I'm done", and then I use `i` which is where I expected it to be.

I get your point, you see foreach() as raw translate to the for-loop and I'm fine with that. To automatically popFront() on break also is only a suggestion if there is no other mechanism to the tell the range we have cancelled it.


It becomes useless for foreach() because you can't rely on them if other code breaks the loop and you need to use that range, like in my case. But also for ranges - there is no need for a popFront() if it is not called in a logic way. Then even empty() could fetch next data if needed. It only makes sense if language system code uses it in a strictly order and ensures that this order is always assured.

There is no problem with the ordering. What seems to be the issue is that you aren't used to the way ranges work.

Ehm, no...
-> empty()
-> front()
-> popFront()
-> empty()
-> front()
break;

-> empty();
-> front();

clearly violates the order for me.
Well, nobody said that we must move on the range - but come on...

What's great about D is that there is a solution for you:

```d
struct EagerPopfrontRange(R)
{
   R source;
   ElementType!R front;
   bool empty;
   void popFront() {
     if(source.empty) empty = true;
     else {
        front = source.front;
        source.popFront;
     }
   }
}

auto epf(R)(R inputRange) {
   auto result = EagerPopfrontRange!R(inputRange);
   result.popFront; // eager!
   return result;
}

// usage
foreach(v; someRange.epf) { ... }
```

Now if you break from the loop, the original range is pointing at the element *after* the one you last were processing.

This is nice. But foreach() should do it automatically - avoiding this. foreach() should be seen as a special construct that does that, not just a dumb alias for the for-loop. Why? Because it is a convenient language construct and usage should be easy. Again, there should be no additional popFront() just because I break the loop.


I'm surprised you bring PHP as an example, as it appears their foreach interface works EXACTLY as D does:

Yeah, but the point is, there is a rewind() method. That is called every time on foreach().


Reply via email to