The rap against "while True:" loops

K

kj

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"?

TIA!

kynn
 
M

Mensanator

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"?
 
K

kj

In said:
If you know this "exit that is always reached",
why do you pretend not to know it by writing
"while True"?

There's no "pretense" of anything. I just happen to prefer the
directness of this:

while True:
...
if test_that_always_succeeds_eventually():
break
...

over the unnecessary fussiness of this:

my_prissy_little_indicator_variable = True
while my_prissy_little_indicator_variable:
...
if test_that_always_succeeds_eventually():
my_prissy_little_indicator_variable = False
continue # oh boy this is going to be fun!
...

In fact, if it were up to me, I would have made the fundamental
looping construct something like

repeat:
...
if whatever():
break
...

and made all the other looping constructs as syntatic sugar for
this one.

kj
 
B

Björn Lindqvist

I have many times screwed up "while True"-loops. When I thought I had
a safe exit condition which turned out to be never reached in some
rare corner cases. Leading to weird bugs with hanging threads. I have
seen colleges screw up in the same way too. Often it is possible to
reformulate "while True" to a generator which I think is much
preferable (such as in the event loop example). Recursive functions
can also be more readable than "while True" because it is easier to
make the exit condition explicit. But sometimes they are necessary and
then you have to be careful to check that the "while True" always
breaks somewhere.
 
M

Mensanator

There's no "pretense" of anything. �I just happen to prefer the
directness of this:

while True:
� � ...
� � if test_that_always_succeeds_eventually():
� � � � �break
� � ...

over the unnecessary fussiness of this:

my_prissy_little_indicator_variable = True
while my_prissy_little_indicator_variable:
� � ...
� � if test_that_always_succeeds_eventually():
� � � � my_prissy_little_indicator_variable = False
� � � � continue �# oh boy this is going to be fun!
� � ...

In fact, if it were up to me, I would have made the fundamental
looping construct something like

repeat:
� � � ...
� � � if whatever():
� � � � � �break
� � � ...

So, the second set of '...' doesn't get executed.

When I use

while not done:
...
if n==1: done = True
...

the loop will actually complete (which is what
I want) instead of aborting, like yours does.
I just don't want the loop to execute again.

If there are things that should not be done,
I explicity have the code check that:

...
if not done: write_to_file(test)
...

But even if some things are skipped, others
need not be:

....
n += 1
...

Now, if I did a break before writing to the file,
I would have to do all kinds of clean-up code
outside the loop, code that would be run only
if the exit were abnormal.
and made all the other looping constructs as syntatic sugar for
this one.

Luckily, it's not up to you.
 
D

Dennis Lee Bieber

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"?
Well... Ada's basic loop structure IS an endless loop...

loop
-- do stuff
end loop;

From which the common exit is

exit when <condition>;


Python's equivalent would be

while True:
#do stuff

And the exit would be

if <condition>: break


Granted, Ada's loop statement is, uhm, expandable

while <condition> loop

and

for index in start...end loop


Praise Frith you aren't looking at REXX's loop construct.

for x = 1 to <something> step <another> while <condition> do
 
T

Terry Reedy

kj said:
I use "while True"-loops often, and intend to continue doing this
"while True",

Me too. Of course, in Python, 'while True' actually means 'while ^C not
pressed and window not closed and process not killed:',
whereas in old mainframe Fortran the equivalent might have meant 'while
my account not emptied', which tended to engender a fear of such loops.

tjr
 
B

Bearophile

Peter Billam:
I remember in the structured-programming revolution the
   loop { ... if whatever {break;} ... }
idiom was The Recommended looping structure, because the code is
more maintainable.

I think "break" was almost the antithesis of structured programming,
it was seen as the little (and a bit more well behaved) brother of
"goto".
Too many "breaks" turn code almost into Spaghetti, that is the
opposite of structured programming.

 With a   while () {...}   idiom, you commit
yourself to a bug-prone rewrite if you ever need to insert a
statement before the first break-test,  and likewise with a
repeat { ... } until ()   you commit yourself to a rewrite if
you ever need to insert a statement after the last break-test.

I think while True:... is used often in Python because Python lacks
still a do-while (or repeat-until, but this is less nice, because the
condition is reversed compared to the one you use in a while-do loop)
construct.
Give me a do-while and a good amount of breaks&while True in my Python
code will be removed.

Bye,
bearophile
 
H

Hendrik van Rooyen

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"?

Others have given various valid answers, but I have not seen this one:

It is often necessary, in long running applications, to set up loops that you
would really like to run until the end of time. - the equivalent of a "serve
forever" construct. Then while True is the obvious way to spell it.

- Hendrik
 
S

Steven D'Aprano

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"?

Such an injunction probably made more sense back in the days of single-
tasking computers. Back in ancient days when dinosaurs walked the Earth,
and I was programming in THINK Pascal on Apple Macintosh System 6, I'd go
into nervous palpitations writing the equivalent of "while True" because
if I got it wrong, I'd lock up the machine and need to hit the power
button. (At least if I was still testing in the THINK Pascal IDE, and had
the whole range of debugging options turned on, I could interrupt it.)

These days, I must admit I still have a tiny little shiver whenever I
write "while True", but that's entirely irrational and I pay no attention
to it.
 
G

Grant Edwards

It is often necessary, in long running applications, to set up
loops that you would really like to run until the end of time.
- the equivalent of a "serve forever" construct. Then while
True is the obvious way to spell it.

Once upon a time I was working on the software requirements
specifications for a missile launcher for the US Navy. In the
section on the system's scheduler task I wrote something like
this:

The scheduler shall consist of an infinite loop that executes
the following:

1. Call this function.

2. Call that function.

[...]

The review team (mainly from Johns Hopkins University Applied
Physics Lab) told me I couldn't put an infinite loop in the
requirements document.

I replied, "OK, when or under what circumstances do you want
the launcher to stop working?"

They said that I misunderstood their comment. I can (and
indeed must) have an infinite loop in the software. I just
can't put the phrase "infinite loop" in the document. They
explained that ship captains get to review these documents.
Ship captains all took a year of undergrad FORTRAN programming
and therefore believe that an infinite loop is a bad thing.

I changed the text to read something like this:

The secheduler shall repeatedly execute the following until
the system is powered off or reset:

1. Call this function.

2. Call that function.

[...]

Everybody was happy.

Tax dollars at work...
 
G

Gabriel Genellina

I have many times screwed up "while True"-loops. When I thought I had
a safe exit condition which turned out to be never reached in some
rare corner cases. Leading to weird bugs with hanging threads. I have
seen colleges screw up in the same way too.

But that's not a problem with the "while True:" construct, that's a
problem with your condition. Had you written the code using "while
some_condition:" it would have failed in the same way.
[...] Recursive functions
can also be more readable than "while True" because it is easier to
make the exit condition explicit. But sometimes they are necessary and
then you have to be careful to check that the "while True" always
breaks somewhere.

That's true for any loop. The only difference is, with a "while
condition:" loop, the condition is right at the while statement. In a
"while True:" loop, you have to look for the condition elsewhere (likely,
an "if" statement preceding a "break").
 
B

bartc

Mensanator said:
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.
 
M

Mensanator

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.

And when I'm in the early stages of a
while not done:
loop, it performs the exact same functionality
while I'm working out what the terminating
conditions are.
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.

Yes, that's a problem and is a good reason to
avoid doing such a thing. With multiple breaks,
your loop may not properly terminates which may
put an unecessary burden on the code which
follows the loop. Seeing the trees is important,
but not at the expense of the forest.
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.

Fine, but the OP is coaching others on how to
program. I've not seen any evidence in this thread
that "while true" is considered "best practice".
 
P

Philip Semanchuk

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.

In addition, isn't it easier to figure out how this loop ends --

while (condition1) and (condition2) and (condition3):
...lots of code here...

than this one?

while True:
...lots of code here...
if not condition1:
break
...lots of code here...
if not condition2:
break
...lots of code here...
if not condition3:
break


My $.02,
Philip
 
R

RDrewD

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".
 
G

Gabriel Genellina

En Sun, 11 Oct 2009 19:46:06 -0300, Philip Semanchuk
Mensanator said:
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".[...]

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.

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 don't think so; forcing ALL loops to have the condition at the start is
unnatural in some cases. Some loops are best written with the condition at
the end (do/while or repeat/until in Pascal) and some loops require a test
in the middle (in Python, while True: + break, because we don't have an
unconditional loop).
In addition, isn't it easier to figure out how this loop ends --

while (condition1) and (condition2) and (condition3):
...lots of code here...

than this one?

while True:
...lots of code here...
if not condition1:
break
...lots of code here...
if not condition2:
break
...lots of code here...
if not condition3:
break

For a loop that can be written as the first one above, sure, that's pretty
explicit.
For a loop as the second one, try to rewrite it with the condition at the
start: you'll end with duplicated tests and/or duplicated code and/or
artificial boolean variables added.

Some algorithms are *naturally* expressed as a loop with the condition in
the middle. Forcing the condition to always happen at the start requires
artificial steps that complicate unnecesarily the code.
 
G

Gabriel Genellina

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.

I think you meant the other way; the above is the simplest loop case, with
the test at the start. A loop with the test at the end, on the other hand,
is slightly harder to prove correct (but not much).

As an example, Ada has a general loop construct like this:

loop
...
exit when some_condition;
...
end loop;

and LOTS of work has been done in proving correctness of Ada programs, so
having the test at the start/middle/end of the loop is not an obstacle for
formal verification.
 
D

Dennis Lee Bieber

Some algorithms are *naturally* expressed as a loop with the condition in
the middle. Forcing the condition to always happen at the start requires
artificial steps that complicate unnecesarily the code.
Though Python has reduced the need for that some... Since one has
the simple

for lin in file_object:
do something with lin

whereas something like old FORTRAN (well, not that old, we'll give it a
while statement -- though after 7 years I've forgotten details)

read(file_unit, stat=ios, format=..., lin)
while (ios .ne. EOF)
do something with lin
read(file_unit, stat=ios, format=..., lin)
end while

which leads to potential error if one read statement is changed, but not
the other. In this situation, the middle exit works best -- using
non-optimal Python

while True:
lin = file_object.readline()
if not lin: break
do something with lin

 
G

greg

Steven said:
Back in ancient days when dinosaurs walked the Earth,
and I was programming in THINK Pascal on Apple Macintosh System 6, I'd go
into nervous palpitations writing the equivalent of "while True" because
if I got it wrong, I'd lock up the machine and need to hit the power
button.

That was true when just about *anything* went wrong in that
environment, though -- I don't think you can blame while True
in particular for it.

(I remember my earliest Mac programming experiences, back
when the Mac was too small to run its own development
environment, and everything had to be cross-compiled.
Debugging consisted of counting the number of times
SysBeep got called before the bomb icon appeared...)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top