Coder Perfect

What is the best way to simulate a do-while loop?

Problem

In a Python program, I need to simulate a do-while loop. Unfortunately, the following simple code does not function:

list_of_ints = [ 1, 2, 3 ]
iterator = list_of_ints.__iter__()
element = None

while True:
  if element:
    print element

  try:
    element = iterator.next()
  except StopIteration:
    break

print "done"

It outputs the following output instead of “1,2,3,done”:

[stdout:]1
[stdout:]2
[stdout:]3
None['Traceback (most recent call last):
', '  File "test_python.py", line 8, in <module>
    s = i.next()
', 'StopIteration
']

What can I do to intercept the’stop iteration’ exception and appropriately break the while loop?

As pseudocode, an illustration of why such a thing could be required is presented below.

State machine:

s = ""
while True :
  if state is STATE_CODE :
    if "//" in s :
      tokens.add( TOKEN_COMMENT, s.split( "//" )[1] )
      state = STATE_COMMENT
    else :
      tokens.add( TOKEN_CODE, s )
  if state is STATE_COMMENT :
    if "//" in s :
      tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )
    else
      state = STATE_CODE
      # Re-evaluate same line
      continue
  try :
    s = i.next()
  except StopIteration :
    break

Asked by grigoryvp

Solution #1

I’m not sure what you’re attempting. A do-while loop can be implemented as follows:

while True:
  stuff()
  if fail_condition:
    break

Or:

stuff()
while not fail_condition:
  stuff()

What are you doing trying to use a do while loop to print the stuff in the list? Why not simply use:

for i in l:
  print i
print "done"

Update:

So, do you have a line-by-line list? And you want to keep going over it again and again? How about this:

for s in l: 
  while True: 
    stuff() 
    # use a "break" instead of s = i.next()

Is that something that comes close to what you’re looking for? It would be as follows, using your code as an example:

for s in some_list:
  while True:
    if state is STATE_CODE:
      if "//" in s:
        tokens.add( TOKEN_COMMENT, s.split( "//" )[1] )
        state = STATE_COMMENT
      else :
        tokens.add( TOKEN_CODE, s )
    if state is STATE_COMMENT:
      if "//" in s:
        tokens.append( TOKEN_COMMENT, s.split( "//" )[1] )
        break # get next s
      else:
        state = STATE_CODE
        # re-evaluate same line
        # continues automatically

Answered by Tom

Solution #2

Here’s a quick and dirty approach to make a do-while loop:

condition = True
while condition:
    # loop body here
    condition = test_loop_condition()
# end of loop

A do-while loop has two main characteristics: the loop body always executes at least once, and the condition is assessed at the bottom of the loop body. Without the use of exceptions or break statements, the control structure shown below achieves both of these goals. It does, however, add one more Boolean variable.

Answered by powderflask

Solution #3

My code below may be useful in demonstrating the primary difference between do-while and while, as far as I can see.

So, in this scenario, you must complete the loop at least once.

first_pass = True
while first_pass or condition:
    first_pass = False
    do_stuff()

Answered by evan54

Solution #4

do {
  stuff()
} while (condition())

->

while True:
  stuff()
  if not condition():
    break

You can perform the following function:

def do_while(stuff, condition):
  while condition(stuff()):
    pass

However, 1) it is unsightly. 2) The condition should be a one-parameter function that is designed to be populated with data (this is the sole reason not to use the conventional while loop).

Answered by ZeD

Solution #5

Because an exception will break the loop, you should handle it outside of it.

try:
  while True:
    if s:
      print s
    s = i.next()
except StopIteration:   
  pass

The issue with your code, I believe, is that the behavior of break inside except is not defined. Break usually just travels one level up, thus break inside try, for example, goes straight to finally (if one exists) an out of the try, but not out of the loop.

http://www.python.org/dev/peps/pep-3136 is a related PEP. Breaking out of nested loops is a similar question.

Answered by vartec

Post is based on https://stackoverflow.com/questions/743164/how-to-emulate-a-do-while-loop