The rap against "while True:" loops

RDrewD drewlist at gmail.com
Sun Oct 11 22:01:47 EDT 2009


On Oct 11, 6:46 pm, Philip Semanchuk <phi... at semanchuk.com> wrote:
> On Oct 11, 2009, at 5:51 PM, bartc wrote:
>
>
>
> > Mensanator wrote:
> >> On Oct 10, 3:15 pm, kj <no.em... at please.post> wrote:
> >>> I'm coaching a group of biologists on basic Python scripting. One
> >>> of my charges mentioned that he had come across the advice never
> >>> to use loops beginning with "while True". Of course, that's one
> >>> way to start an infinite loop, but this seems hardly a sufficient
> >>> reason to avoid the construct altogether, as long as one includes
> >>> an exit that is always reached. (Actually, come to think of it,
> >>> there are many situations in which a bona fide infinite loops
> >>> (typically within a try: block) is the required construct, e.g.
> >>> when implementing an event loop.)
>
> >>> I use "while True"-loops often, and intend to continue doing this
> >>> "while True", but I'm curious to know: how widespread is the
> >>> injunction against such loops? Has it reached the status of "best
> >>> practice"?
>
> >> If you know this "exit that is always reached",
> >> why do you pretend not to know it by writing
> >> "while True"?
>
> > When I'm starting to code something I haven't yet fully worked out,  
> > it often starts with an infinite loop like this, until the body is  
> > coded and I've figured out how to escape from it.
>
> > At the end if may or may not be tidied up, depending on how much  
> > work it is to reconcile several possible break points into a single  
> > terminating condition to be place at one end, and whether that is  
> > likely to break or obfuscate a currently working program.
>
> > But if it's never going to be seen by the brigade who hate all  
> > break, exit, goto and multiple return statements, then I won't bother.
>
> I think you bring up a good point. I think "while True" has some  
> legitimate uses (like event loops), and I don't mind seeing it there.  
> What I don't like is goto, and to a lesser extent break, exit, and  
> multiple returns. I don't find too many cases where they're the  
> clearest way to express things. And where one sees a "while True", one  
> can almost always find a "break" or two lurking in the loop.
>
> IMHO, break, goto, etc. have their place, but they're ripe for abuse  
> which leads to spaghetti code. Since the OP is teaching non-
> programmers to write code, I think the potential for abuse is  
> especially important to keep in mind. I'd think that teaching them a  
> tool like "while True" would encourage the "code now, design later"  
> trap that even experienced programmers -- including myself --  
> sometimes fall into. Writing "while <condition>" instead forces one to  
> stop at the beginning of the loop and think at least a little about  
> exactly what it's meant to accomplish.

I was a bit surprised that nobody in this discussion so far bantered
around the phrase "loop invariant", but then I looked in
http://en.wikipedia.org/wiki/Loop_invariant and found it was draped in
so much formalism that it's sure to put off all but the most dedicated
of Computer Science fans.   I haven't been in college in 35 years, so
I'll admit to being rusty on this, but as I remember it, any time we
wrote a loop, we were expected to be able to say what the loop
invariant is.

my_prissy_little_indicator_variable = true
while (my_prissy_little_indicator_variable){
    <body>
}
isn't satisfying because it doesn't guard the <body> with any
assurance that the loop invariant will be true before you enter into
that block of code.

Similarly, the

Repeat {
    <first part>
    if (<exit condition>) break
    <second part>
}

doesn't guard the <first part> code.   Worse, when you get to the
Repeat in reading the code, you get no clue about when the loop will
terminate, except maybe for a comment that someone helpfully put by
the loop, but as the program evolves, the comments often lie.

I don't mind while(true) for the case of "do forever" like those
launcher requirements Peter Billam wrote about up above in this
thread.   It essentially says the loop invariant is that the system
hasn't crashed yet.   But beware of the "universal structured
program":

pc=1
while(pc!=0){
    select(pc){
        case 1:
           <body1>
           pc=<next block #>
           continue
        case 2:
           <body2>
....
    }
}
# Look Ma!   No goto statements

There are no goto statements but the "universal structured program"
has no meaningful "structure" visible to the casual reader's eye..
By making the setting of PC in each case be conditional, you can send
the program to any <bodyN> that you want.   (Think of pc as standing
for "program counter" and you can see this has as much structure as
assembler language.   Very hard to judge that the code always keeps
array references within bounds and that all loops are only entered
when the loop invariant holds and that the loops always terminate when
the loop invariant no longer holds.  You might as well be programming
like its 1959.  See, it wasn't just the presence of goto's that was
harmful, it was the lack of careful construction of the program that
was harmful.

And just to dust off a fun paper from the past that explores
programming structures that might be needed if you care about every
last branch instruction as you carefully construct your program, see
http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf, Knuth's
classic "Structured Programming with Go To statements".  ("Do you
suffer from painful elimination?").

R. Drew Davis
Cornell '74
Bell Labs, "retired".



More information about the Python-list mailing list