In PHP we have the for and foreach loops, which are both handy, but there is
a case where a 3rd type of for loop would be handy: Iterators.
With 5.5 it became super easy to use Iterators, by simple creating a Generator. While
working on my itertools port to PHP (here), I found a situation where both the for and foreach constructs fell short.
I had created counter Generator which just creates an Iterator that starts at a given number and counts indefinitely. Then, I wanted to create a version of range which used an Iterator. Now, I could do this with a few for loops like in the PHP docs, but I wanted to use my new fancy counter function, so I started with a for loop:
<?php
for ($c = counter($start, $step); $c->current() <= $end; $c->next()) {
yield $c->current();
}Pretty simple, but ugly. So I tried it with a foreach loop:
<?php
foreach (counter($start, $step) as $i) {
yield $i;
if ($i === $end) {
break;
}
}A little bit better, but could still be better.
After being annoyed by this, I had an idea for a new type of loop; the "foreach until" loop:
<?php
foreach (counter($start, $step) as $i) until ($i === $end) {
yield $i;
}This could be useful in all sorts of situations. I know a lot of people may not want to add a new keyword to PHP, so there is an alternative as well.
Same thing as above, except it is "while n is true" instead of "until n is true":
<?php
foreach (counter($start, $step) as $i) while ($i !== $end) {
yield $i;
}Thoughts?
The while or until checks should happen after the body of the foreach has been executed. This will keep it in-line with the current do...while loop construct.
We could also keep it more in-line with the do...while construct and append the while or until expressions to the end of the loop:
<?php
foreach (counter($start, $step) as $i) {
yield $i;
} until ($i === $end);and
<?php
foreach (counter($start, $step) as $i) {
yield $i;
} while ($i !== $end);I do not prefer this syntax personally, but it is more consistent with the other loops.
encountered this situation a lot of times, should be included, I say +1