Pro: better fit between syntax and logic
For some algorithms, do ... while loops are the most natural way to express the program logic and prevent code duplication. Consider the example mentioned in the question:
do {
position = random_coords();
} while (is_inside_wall(position));
That is, we want to pick a random position and then repick as long as the position is inside a wall.
If do ... while loops are not available, this code will probably be written as a while loop instead. The best way to translate the logic is not obvious. One could pull the initial pick out ahead of the loop:
position = random_coords();
while (is_inside_wall(position)) {
position = random_coords();
}
This code is pretty readable but violates the don't repeat yourself maxim--not too badly in this case, but it gets worse if the body of the loop is more than one statement.
Alternately, we could use a sentinel value to "disable" the check on the first iteration. This could be a separate variable:
var position_set = false;
while (!position_set || is_inside_wall(position)) {
position = random_coords();
position_set = true;
}
Or, in some cases, a known invalid value of the variable we're checking:
position = null;
while (position == null || is_inside_wall(position)) {
position = random_coords();
}
These approaches add complexity and obscure the real loop condition.
Finally, maybe the worst option (though one that I admit I have used before): write an infinite loop and break out of it once the condition is satisfied:
while (true) {
position = random_coords();
if (!is_inside_wall(position)) {
break;
}
}
This obscures the algorithm even more severely and is highly prone to accidental infinite loops.
In any case, none of these while-loop options read as cleanly as the do ... while version.
while { ...body; cond } {}
instead of the oldwhile (cond) {...body}
. Looks a lot uglier than do while loops, though $\endgroup$