OLYMPUS DIGITAL CAMERA

Sometimes, they are demonized, and sometimes, they are useful. Infinite loops come in a variety of options in PHP, so let’s put them neatly on a shelf, with all theirs variations.

Classic while (true)

To make an infinite loop, the most simple is to take a loop, and make it unconditional. The poster child for this is while (true).

Using do...while(true)

Obviously, do...while can do the same than while, but it is seldom mentionned anywhere. Indeed, do...while is roughly used 10 times less than while.

The main difference is that the loop will be executed at least one, but with infinite loop, what differences does this make?

With for (;;)

Another big star of the infinite loops is the empty for(). Here, the loop uses 3 expressions, which are initialization, terminaison and increment. Usually, removing terminaison or increment lead both to infinite loop.

In the end for (;;) is a lot more readable.

Using a Generator with foreach()

Let’s move to foreach(). This one is naturally bounded: foreach() reads all the values in the provided source. This means that no source build on an array can be infinite: PHP will never build an infinite array before running out of memory.

So, we can use a generator. Let’s see how this works:

To be honest, this is a bit cheating. There is a hidden while(true) hidden in the generator, which is actually creating the infinite loop. Let’s see if we can do better.

Using an inifinite Generator with foreach()

To get rid of the while(true) in the generator, we can rely on our good old friend yield from. While yield emits one value, yield from can do the same from an array, or another generator. We just need to get an infinite number of generators.

Or, we can use the same one, and pass it an argument. It is lesser known that generators can take arguments, but this works. Here, the second generator is initialized with the previous last value. This builds an infinite recursion.

Compared to the previous examples, it certainly less efficient, as the recursive calls are creation nested execution contexts. We might exhaust the memory before reaching the infinite…. (sic).

Infinite foreach() by itself

One trick of foreach() is that it works on a copy of the initial array. This is a default security to make loops finite. But, foreach() also ensures that all the keys of the source array are actually used.

So, when the foreach() works with references, it actually switches to using the original array, as it may have to updates its values. Then, it runs over all the keys, but now, the keys may be changed by writing again in the same array. The trick is to create only new keys in the source array.

And also, to start with one value in the array, at least. Otherwise, PHP skips the whole loop.

Using goto

We could not avoid mentioning goto as a great tool to build infinite loops. After all, all the loops above are built on top of a hidden goto.

Just don’t tell anyone I mentionned it, there are goto-haters in the wild.

Using a Recursive Function

Finally, it is possible to skip entirely the loops by relying on recursive functions. Just skip the terminating condition.

We already ran into a variation of this, with the recursive generator. It was not the yield that was critical, but the recursion.

Infinite loops are useful, with indefinite waiting loops, such as event loops. This is when there is no limit to what may happen, so looping again and again is important.

In the other cases, it is better to know how to write an infinite loop. Not to use it, but very well to avoid running it in production.

Share.
Leave A Reply