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().