This is sort of an indirect answer, but this question got me thinking about the logic behind it, and I thought this might be worth sharing.
As everyone else has said, you use a do ... while
loop when you want to execute the body at least once. But under what circumstances would you want to do that?
Well, the most obvious class of situations I can think of would be when the initial ("unprimed") value of the check condition is the same as when you want to exit. This means that you need to execute the loop body once to prime the condition to a non-exiting value, and then perform the actual repetition based on that condition. What with programmers being so lazy, someone decided to wrap this up in a control structure.
So for example, reading characters from a serial port with a timeout might take the form (in Python):
response = []
char_read = port.read(1)
while char_read:
response.append(char_read)
char_read = port.read(1)
# When there's nothing to read after 1s, there is no more data
''.join(char_read)
Note the duplication of code: char_read = port.read(1)
. If Python had a do ... while
loop, I might have used:
do:
char_read = port.read(1)
response.append(char_read)
while char_read
The added benefit for languages that create a new scope for loops: char_read
does not pollute the function namespace. But note also that there is a better way to do this, and that is by using Python's None
value:
response = []
char_read = None
while char_read != '':
char_read = port.read(1)
response.append(char_read)
''.join(char_read)
So here's the crux of my point: in languages with nullable types, the situation initial_value == exit_value
arises far less frequently, and that may be why you do not encounter it. I'm not saying it never happens, because there are still times when a function will return None
to signify a valid condition. But in my hurried and briefly-considered opinion, this would happen a lot more if the languages you used did not allow for a value that signifies: this variable has not been initialised yet.
This is not perfect reasoning: in reality, now that null-values are common, they simply form one more element of the set of valid values a variable can take. But practically, programmers have a way to distinguish between a variable being in sensible state, which may include the loop exit state, and it being in an uninitialised state.