It seems to me that a while loop with the appropriate break statements can replace them entirely. I understand that a break statement may not feel as “smooth” as a for loop that does something a specified number of times, but I also feel that the redundancy in their behavior is unnecessary.
3
I suspect part of the answer is that it makes compiler optimisation easier, and partly because, for some code variants, it’s easier for a human to read a simple ‘for’ structure than searching for a break statement.
Human readable/maintainable and compiler optimisable code is more important than considerations of functional redundancy in language design – after all, where do you stop, you can write language with a single control flow structure in it (think of a Turing-complete language based on a ‘move’ from pre-defined function to function in a list popping manner akin to a single instruction machine language), but no one would want to use it.
1
For loops are needed because they best express the programmers intent. Which is why most languages have several types of loops.
Excluding languages like BrainFuck, the point of most languages syntax is to make it easier to express the programmers intent. Otherwise we’d all stick with the perfectly viable macine code.
What is more readable and maintainable is the correct way to do most things.
Explicit is better than implicit.
Pseudo Code Examples:
for (int i=0; i < 10; i++) { /* do something 10 times */ }
for i in range(1,10): # do something 10 times
// assume range is a list, set, vector, array or iterable something
for (final int i : range) { /* do something 10 times */ }
vs
int i = 0;
while (i < 10) { /* do something 10 times */ i++; }
which is just syntactic sugar for and not much better than:
int i = 0;
loop:
if (i < 10) { /* do something */ } else { goto end; }
i++; goto loop;
end:
-
Which one immediately tells you what is going on?
-
What happens if someone moves the
i++
in thewhile
version? -
what happens if someone forgets the
i++
in thewhile
version? -
Which one has better locality and cohesion ( hint it is the for version )
-
the
while
version has mutable state that is outside the scope of the loop!
Even better are languages, mostly functional ones, that support pattern matching such as Erlang
Here is pseudo code for a pattern matching version.
function for(n) { /* do something */ for(n--); }
function for(0) { /* do something the last time*/ }
Most looping is over some kind of collection
The Visitor Pattern
is much more expressive and has high cohesion and low coupling.
Here is a good example in Python with a thorough explanation of why it is so powerful.
2
An oft-taught rule of thumb in programming classes, and a generally handy way to think about it, is this:
If you aren’t sure how many times a loop might run (it could be one time or a hundred times, like when searching for something in a tree), use while()
.
If you you can define precisely how many times a loop will execute, such as 10 times, or on a set range of items (like the first n items of a list), use for()
.
Strictly speaking, you don’t need for or while loops in any language that has goto
or repeatedly executed main
method.
while
loops also have the dubious distinction of being probably the most common source of infinite loop bugs in modern programming languages, and they tend to expand the current scope with unneeded iterator variables unless you use a closure (and a language that supports closures, of course). For beginners, they can be a real pain.
For experienced programmers, it’s best to understand the idioms of the language and what each type of loop is commonly understood to represent, and to avoid shoe-horning one’s one personal preferences onto every problem if the code is ultimately meant for other people’s consumption.
I, on the other extreme, tend to prefer for
and foreach
or for-range
(in languages that have them) and have to force myself to use while
loops when they seem most appropriate.
It need not be a religious thing – just learn the use of all basic building blocks of language and especially all the finer ins and outs of control structures when you can, and you’ll find it’s time very well spent.