fun with nested loops

aspineux aspineux at gmail.com
Wed Aug 31 18:35:45 CEST 2011


On Aug 31, 5:51 pm, Daniel <dali... at gmail.com> wrote:
> Dear All,
>
> I have some complicated loops of the following form
>
> for c in configurations: # loop 1
>     while nothing_bad_happened: # loop 2
>         while step1_did_not_work: # loop 3
>             for substeps in step1 # loop 4a
>                 # at this point, we may have to
>                 -leave loop 1
>                 -restart loop 4
>                 -skip a step in loop 4
>                 -continue on to loop 4b
>
>         while step2_did_not_work: # loop 4b
>             for substeps in step2:
>                 # at this point, we may have to
>                 -leave loop 1
>                 -restart loop 2
>                 -restart loop 4b
>                 ...
>         ...many more loops...
>
> I don't see any way to reduce these nested loops logically, they
> describe pretty well what the software has to do.
> This is a data acquisition application, so on ever line there is
> a lot of IO that might fail or make subsequent steps useless or
> require a
> retry.
>
> Now every step could need to break out of any of the enclosing loops.
> So basically I have to transform every loop to be of the following
> horror:
>
> # general transformation of
> # "for c in configurations..."
> # to provide restart, break and continue
> # callable from any nesting level inside of the loop
>
> class loop1_restart(Exception): pass
> class loop1_break(Exception): pass
> class loop1_continue(Exception): pass
>
> while True:
>     try:
>         for c in configurations:
>             while True:
>                 try:
>                     # inner loops go here, of course, they would have
> to get
>                     # all the boilerplate added, too
>                     while nothing_bad_happened:
>                         while step1_did_not_work:
>                            if cond1:
>                                raise loop1_restart()
>                            elif cond3:
>                                raise loop1_break()
>                            elif cond3:
>                                raise loop1_continue()
>
>                     break
>
>                 except loop1_continue:
>                     pass
>         break
>     except loop1_restart:
>         pass
>     except loop1_break:
>         break
>
> Of course this is extremely tedious and error prone.
> If Python had named loops (PEP 3136, unfortunately rejected), this
> would be trivial:
> In Fortran I can continue (cycle), break (exit) and redo (goto label)
> arbitrary
> loops, which results in neat code:
>
> 10 loop1: do I=1,3
>     loop2: do J=1,4
>         print *,I,J
>         goto 10
>         cycle loop1
>         exit loop1
>     enddo loop2
> enddo loop1
>
> My question is, how do I obtain something that implements the
> following logic:
>
> @named_loop(fred) # I wish this would be possible
> for i in range(10):
>     for j in range(10):
>         break fred # breaks out of outer loop
>         continue fred # continues outer loop
>         redo fred # resets outer loop and restarts with i=0
>
> The best solution would be something along the Proposal D - Explicit
> iterators
> in PEP 3136, in this case it would even be possible to peek at the
> next i or
> advance/reverse the iterator a few steps.
>
> Has anyone an idea on a nice way to write breaks/continues/redos for
> deeply
> nested loops?

Hi Dan, it looks like you have already answered all your questions.

one more idea, a kind of named loop:

ic=0
op='what to do'
while ic<len(configurations):
    c=configuration[ic]

    if op=='restart':
        ic=0
    elif op=='next'
        ic+=1
    elif op=='terminate'
        ic=len(configurations)

and at first explicit iterator was also a good idea, when you don't
need to iter in reverse order

When it become too complicate, I use state machine:
http://en.wikipedia.org/wiki/Finite-state_machine


Regards


>
> Dan




More information about the Python-list mailing list