The rap against "while True:" loops

21 views
Skip to first unread message

kj

unread,
Oct 10, 2009, 4:15:21 PM10/10/09
to


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

Mensanator

unread,
Oct 10, 2009, 5:20:35 PM10/10/09
to

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

>
> TIA!
>
> kynn

kj

unread,
Oct 10, 2009, 6:02:37 PM10/10/09
to
In <01ccc46d-5ea9-4dfe...@v36g2000yqv.googlegroups.com> Mensanator <mensa...@aol.com> writes:

>On Oct 10, 3:15=EF=BF=BDpm, kj <no.em...@please.post> wrote:
>> I'm coaching a group of biologists on basic Python scripting. =EF=BF=BDOn=


>e
>> of my charges mentioned that he had come across the advice never

>> to use loops beginning with "while True". =EF=BF=BDOf 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. =EF=BF=BD(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? =EF=BF=BDHas it reached the status of "bes=
>t
>> practice"?

>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

Björn Lindqvist

unread,
Oct 10, 2009, 6:32:25 PM10/10/09
to kj, pytho...@python.org
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.

2009/10/10 kj <no.e...@please.post>:

> --
> http://mail.python.org/mailman/listinfo/python-list
>

--
mvh Björn

Mensanator

unread,
Oct 10, 2009, 6:34:36 PM10/10/09
to
On Oct 10, 5:02�pm, kj <no.em...@please.post> wrote:

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.

>
> kj

Peter Billam

unread,
Oct 10, 2009, 7:52:13 PM10/10/09
to
On 2009-10-10, kj <no.e...@please.post> wrote:
> 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"?

This trend is ironic; I remember in the structured-programming
revolution the
loop { ... if whatever {break;} ... }
idiom was The Recommended looping structure, because the code is
more maintainable. 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.
Also, it replaces a multitude of idioms (while, repeat, for,
foreach, map, ...) with one simple idiom which works in all
cases, including in all languages (OK, except functional).

The for item in list idiom is wonderfully readable if you
know that's all you'll ever want to do, but for more general
loops there are still arguments in favour of while True

Infinite loops, well they're quickly noticed in development,
just like stack-crashes are in stack-based languages.
They can occur in other loop-idioms too, like if you
append to your list, or adjust the looping index.

JMHO, Regards, Peter

--
Peter Billam www.pjb.com.au www.pjb.com.au/comp/contact.html

Message has been deleted

Terry Reedy

unread,
Oct 11, 2009, 12:33:21 AM10/11/09
to pytho...@python.org
kj wrote:
>
> 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

Bearophile

unread,
Oct 11, 2009, 1:11:57 AM10/11/09
to
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

Hendrik van Rooyen

unread,
Oct 11, 2009, 2:42:53 AM10/11/09
to pytho...@python.org

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

Steven D'Aprano

unread,
Oct 11, 2009, 4:01:51 AM10/11/09
to
On Sat, 10 Oct 2009 20:15:21 +0000, kj wrote:

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


--
Steven

Peter Billam

unread,
Oct 11, 2009, 7:03:18 AM10/11/09
to
On 2009-10-11, Bearophile <bearoph...@lycos.com> wrote:
> 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.

It's multi-level breaks that are danger-prone and were
deprecated; a single-level break is quite safe.

> Give me a do-while and a good amount of breaks&while True
> in my Python code will be removed.

Maybe, but you still commit yourself to a rewrite if you


ever need to insert a statement after the last break-test.

It needs only one tiny extra little requirement in the
wrong place to invalidate a while or a do structure,
but the loop-and-break structure always works,
and that's what gives it its extra maintainability.

Grant Edwards

unread,
Oct 11, 2009, 10:08:19 AM10/11/09
to
On 2009-10-11, Hendrik van Rooyen <hen...@microcorp.co.za> wrote:
>
> 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...

--
Grant

Gabriel Genellina

unread,
Oct 11, 2009, 12:15:16 PM10/11/09
to pytho...@python.org
En Sat, 10 Oct 2009 19:32:25 -0300, Bjï¿œrn Lindqvist <bjo...@gmail.com>
escribiᅵ:

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

--
Gabriel Genellina

bartc

unread,
Oct 11, 2009, 5:51:49 PM10/11/09
to

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.

--
Bartc

Mensanator

unread,
Oct 11, 2009, 6:35:38 PM10/11/09
to
On Oct 11, 4:51�pm, "bartc" <ba...@freeuk.com> wrote:
> Mensanator wrote:
> > On Oct 10, 3:15 pm, kj <no.em...@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.

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

>
> --
> Bartc

Philip Semanchuk

unread,
Oct 11, 2009, 6:46:06 PM10/11/09
to Python-list (General)

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

RDrewD

unread,
Oct 11, 2009, 10:01:47 PM10/11/09
to

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

Gabriel Genellina

unread,
Oct 11, 2009, 10:26:44 PM10/11/09
to pytho...@python.org
En Sun, 11 Oct 2009 19:46:06 -0300, Philip Semanchuk
<phi...@semanchuk.com> escribió:

> On Oct 11, 2009, at 5:51 PM, bartc wrote:
>> Mensanator wrote:
>>> On Oct 10, 3:15�pm, kj <no.em...@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".[...]


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

--
Gabriel Genellina

Gabriel Genellina

unread,
Oct 11, 2009, 11:14:30 PM10/11/09
to pytho...@python.org
En Sun, 11 Oct 2009 23:01:47 -0300, RDrewD <drew...@gmail.com> escribiᅵ:

> On Oct 11, 6:46ï¿œpm, Philip Semanchuk <phi...@semanchuk.com> wrote:
>> On Oct 11, 2009, at 5:51 PM, bartc wrote:
>> > Mensanator wrote:
>> >> On Oct 10, 3:15 pm, kj <no.em...@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.

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.

--
Gabriel Genellina

Message has been deleted

greg

unread,
Oct 12, 2009, 4:02:44 AM10/12/09
to
Steven D'Aprano wrote:
> 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...)

--
Greg

greg

unread,
Oct 12, 2009, 4:28:00 AM10/12/09
to
RDrewD wrote:

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

The loop invariant and the exit condition are different things.

The loop invariant is supposed to be true every time the loop
invariant is tested, including on the last iteration, so that
when the loop exits, you can assert that the loop invariant
*and* the exit condition are both true. The trick is to choose
them so that together they ensure whatever it is the loop is
meant to accomplish.

If the exit test is half way through the loop, then the loop
invariant doesn't have to be true before the loop is entered --
it only has to be true by the time the exit test is encountered
for the first time. In other words, the first execution of the
part of the loop before the exit test is really part of the
initialization, and has to be treated as such in the analysis.

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

I think it's more accurate to say that, because there is no exit
test, there is no point in the loop at which a loop invariant
has to be true, so there is no need for a loop invariant, at least
in the sense the term is used in the formal theory of correctness
proofs for loops.

It may be desirable to impose invariants on the state of the
system at various points in the loop for other reasons, although
those might better be described as parts of the contracts between
the loop and the functions it calls.

(BTW, "the system hasn't crashed yet" can't be the loop invariant,
because if the loop ever exits then it means the system must have
crashed, so the loop invariant is no longer true!)

--
Greg

greg

unread,
Oct 12, 2009, 4:36:34 AM10/12/09
to
Mensanator wrote:

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

Seems to me that 'while not done:' is no better than
'while True:', because in both cases you have to look
inside the loop to find out what the exit condition
is.

Using a more meaningful name for the flag can help,
but you can't teach someone that just by giving them
an overly simplified rules such as "never use
while True:". They'll probably just replace it with
'while not done:' and think they've improved things,
without ever really understanding the issue.

--
Greg

greg

unread,
Oct 12, 2009, 4:42:23 AM10/12/09
to
kj 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".

It's possible this is something he was told in relation to
another language that has more options.

For example, in C there's for(;;) as an alternative, although
there's not much to choose between them. Also you can often
use an assignment-as-condition trick to squeeze a loop-and-
a-half into a while(), and you have do-while loops for
testing at the end.

Python is much more limited -- anything which isn't a
for has to be a while of some shape, so it's harder to
avoid while True without introducing extra complexities
into the code.

--
Greg

Luis Zarrabeitia

unread,
Oct 12, 2009, 9:32:35 AM10/12/09
to pytho...@python.org
On Sunday 11 October 2009 11:56:55 pm Dennis Lee Bieber wrote:
> 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

Actually, in python, this works even better:

for lin in iter(file_object.readline, ""):
... do something with lin

--
Luis Zarrabeitia (aka Kyrie)
Fac. de Matemática y Computación, UH.
http://profesores.matcom.uh.cu/~kyrie

Grant Edwards

unread,
Oct 12, 2009, 10:51:52 AM10/12/09
to
On 2009-10-12, Gabriel Genellina <gags...@yahoo.com.ar> wrote:

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

Except the test at the start is meaningless when it comes to
reading the code and troubleshooting. What counts are
assignments to my_prissy_little_indicator_variable inside the
loop. And those aren't really any easier to spot that "break"
statements.

--
Grant Edwards grante Yow! I want to read my new
at poem about pork brains and
visi.com outer space ...

Mel

unread,
Oct 12, 2009, 10:58:46 AM10/12/09
to
Luis Zarrabeitia wrote:

> On Sunday 11 October 2009 11:56:55 pm Dennis Lee Bieber wrote:
>> 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
>
> Actually, in python, this works even better:
>
> for lin in iter(file_object.readline, ""):
> ... do something with lin

And one can do this oneself. Faced with

while True:
stuff_required_to_make_the_decision()
if the_decision():
break
other_stuff()


Wrapping the `stuff_required_...` and `the_decision` up into a generator
would simplify the statement, and if it were done well the code overall
would probably be better.

Mel.


Luis Zarrabeitia

unread,
Oct 12, 2009, 12:59:34 PM10/12/09
to pytho...@python.org
On Monday 12 October 2009 09:47:23 am Xavier Ho wrote:

> On Mon, Oct 12, 2009 at 11:32 PM, Luis Zarrabeitia <ky...@uh.cu> wrote:
> > Actually, in python, this works even better:
> >
> > for lin in iter(file_object.readline, ""):
> > ... do something with lin
>
> What about ....
>
> >>> with open(path_string) as f:
> >>> for line in f:
> >>> # do something

Gah.

You are right, of course!

Even my for should've been:

for lin in file_object:
...

and nothing more.

I use that iter "trick" only when I don't want the buffering (like, when I'm
reading from stdin in a squid authenticator helper).

I guess that the 'for line in f' is so... natural for me, that the only reason
I could think for writing "while True" for a file iteration was when I needed
to use readline explicitly.

But yes, "with"!

Mensanator

unread,
Oct 12, 2009, 1:35:06 PM10/12/09
to

You're missing the point. It's not that you have to
look inside for the terminating condition. It's that
you don't need a break.

>
> --
> Greg

John Reid

unread,
Oct 12, 2009, 2:02:52 PM10/12/09
to pytho...@python.org

Nothing wrong with a having a break IMHO.

while not done:

seems very dangerous to me as you'd have to

del done

before writing the same construct again. That's the sort of thing that
leads to errors.

Ethan Furman

unread,
Oct 12, 2009, 2:22:17 PM10/12/09
to pytho...@python.org

What's wrong with breaks?

I'll agree that they can be overused and abused, but I am not aware of
*any* programming costruct that cannot be. If you rule out one way of
doing things for every situation you can end up making messes just as
bad as the ones you're trying to avoid.

Good programming, as all good endeavors, requires thinking too.

~Ethan~

Mensanator

unread,
Oct 12, 2009, 2:32:27 PM10/12/09
to
On Oct 12, 1:02�pm, John Reid <j.r...@mail.cryst.bbk.ac.uk> wrote:
> Mensanator wrote:
> > On Oct 12, 3:36 am, greg <g...@cosc.canterbury.ac.nz> wrote:
> >> Mensanator wrote:
> >>> while not done:
> >>> ...
> >>> if n==1: done = True
> >>> ...
> >> Seems to me that 'while not done:' is no better than
> >> 'while True:', because in both cases you have to look
> >> inside the loop to find out what the exit condition
> >> is.
>
> >> Using a more meaningful name for the flag can help,
> >> but you can't teach someone that just by giving them
> >> an overly simplified rules such as "never use
> >> while True:". They'll probably just replace it with
> >> 'while not done:' and think they've improved things,
> >> without ever really understanding the issue.
>
> > You're missing the point. It's not that you have to
> > look inside for the terminating condition. It's that
> > you don't need a break.
>
> Nothing wrong with a having a break IMHO.

My opinion is that there is everything wrong with
having a break. I don't think I have ever used one,
I write code that doesn't depend on that crutch.

>
> while not done:
>
> seems very dangerous to me as you'd have to
>
> del done
>
> before writing the same construct again. That's the sort of thing that
> leads to errors.

Duh. I won't write silly code like that either.
If I need more than one loop structure then I'll
do something like

while not done_with_this


while not done_with_that

Besides, since I _always_ initialize the flag
before entering a loop, the flag can be reused
and doesn't have to be deleted (as long as the
loops aren't nested). And since I don't use goto,
there's no chance the initialization can be avoided.

The best way to avoid the pitfalls of spaghetti
code is to not write it in the first place.

Falcolas

unread,
Oct 12, 2009, 3:18:59 PM10/12/09
to

How do you manage code where you need to drop out of a neatly written
for or while loop early? I don't use break frequently, but just like
gotos, it does have it's place in well written code.

Glad to hear, by the way, that you don't use gotos in Python. =D

Garrick

Mensanator

unread,
Oct 12, 2009, 5:11:17 PM10/12/09
to

I don't. If I thought there would ever be a case when
a for loop had to exit early, I wouldn't use a for loop.

Similarly, if I ever felt the need to escape from a
while loop, I would rewrite it to avoid that situation.

> I don't use break frequently, but just like
> gotos, it does have it's place in well written code.
>
> Glad to hear, by the way, that you don't use gotos in Python. =D

Python doesn't have goto? Gee, I guess I never looked for
one. Learned my lesson from Pascal, eh?

>
> Garrick

David C Ullrich

unread,
Oct 12, 2009, 5:59:55 PM10/12/09
to
kj 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,

Heh-heh: When I read this it occurred to me that another way to
start an infinite loop would be to make a post here on this topic.
Looking at the thread so far it appears I was right.

> 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

Raymond Hettinger

unread,
Oct 12, 2009, 9:00:30 PM10/12/09
to
[kj]

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

This is the first I've ever heard of such an quasi-injunction.
Like you, I use "while True" often. We use it frequently
in the standard library and have no PEP 8 admonition
against it, nor does pychecker report it as a negative practice.
The use of "while 1" loops has a long history in other langauges
as well.

So, if you hear someone make-up a new "best practice" proscibing
"while True", just smile and continue to write programs as you
have been. You will not be alone. Many excellent programmers
write "while True" whenever it is called for.


Raymond

Paul Rubin

unread,
Oct 12, 2009, 9:16:51 PM10/12/09
to
kj <no.e...@please.post> writes:
> 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"?

E. W. Dijkstra used to advocate that every loop have exactly one entry
point and exactly one exit point, i.e. no multiple break statements.
This is probably a misstatement, but I believe that the purpose was to
be able to specify a precondition at the loop entrance and a
postcondition at the exit, and be able to verify the conditions more
straightforwardly than if there were multiple exit points. But, that
doesn't specifically seem to speak against "while True:". For
example, Ada has a loop construct where the test and break is in the
middle of the loop.

Steven D'Aprano

unread,
Oct 13, 2009, 12:48:18 AM10/13/09
to
On Mon, 12 Oct 2009 11:32:27 -0700, Mensanator wrote:

>> Nothing wrong with a having a break IMHO.
>
> My opinion is that there is everything wrong with having a break. I
> don't think I have ever used one, I write code that doesn't depend on
> that crutch.


Using break can avoid a lot of complication in loops. There's no need to
force every loop to have a single exit point (or for that matter, for
every function to have a single return). Compare the straightforward
implementation of a simple linear search:

for item in seq:
if cond(item):
print item
break

versus doing it without a break:

found = False
for item in seq:
if not found and cond(item):
print item

or:

found = False
seq = iter(seq)
while not found:
item = seq.next()
found = cond(item)
if found:
print item

The first is obviously correct, and efficient (it stops searching when it
has found a result). The second and third avoid using a break, but at the
cost of complicated, inefficient code which isn't obviously correct. If
you need to post-process item before returning, it's simple to replace
the return with a break.


> The best way to avoid the pitfalls of spaghetti code is to not write it
> in the first place.


break does not necessarily lead to spaghetti code. Avoiding break just
because it is a "goto" is cargo-cult programming -- following the magic
incantations with no understanding of the *reasons* for when gotos should
be used and avoided.

The danger with goto is that it is an *unstructured* jump. break,
continue, return, yield, for, while are all *structured* jumps. They can
be abused, like anything, but they're not inherently dangerous.

--
Steven

Message has been deleted

John Reid

unread,
Oct 13, 2009, 4:44:22 AM10/13/09
to pytho...@python.org

Mensanator wrote:
>> Nothing wrong with a having a break IMHO.
>
> My opinion is that there is everything wrong with
> having a break. I don't think I have ever used one,
> I write code that doesn't depend on that crutch.

I guess its crutch-iness is in the eye of the beholder. You seem to have
a dogmatic view about this.

>
>> while not done:
>>
>> seems very dangerous to me as you'd have to
>>
>> del done
>>
>> before writing the same construct again. That's the sort of thing that
>> leads to errors.
>
> Duh. I won't write silly code like that either.
> If I need more than one loop structure then I'll
> do something like
>
> while not done_with_this
>
>
> while not done_with_that

This is neither clean or well scoped.

>
> Besides, since I _always_ initialize the flag
> before entering a loop, the flag can be reused
> and doesn't have to be deleted (as long as the
> loops aren't nested). And since I don't use goto,
> there's no chance the initialization can be avoided.

Initialising the flag is just another line of code that has to be
interpreted later. I didn't notice the initialisation in your original post.

>
> The best way to avoid the pitfalls of spaghetti
> code is to not write it in the first place.
>

I agree. With 'break' it is obvious what the code does and there are
fewer lines to write in the first place and comprehend in the second.

Mensanator

unread,
Oct 13, 2009, 11:20:21 AM10/13/09
to
On Oct 13, 3:44�am, John Reid <j.r...@mail.cryst.bbk.ac.uk> wrote:
> Mensanator wrote:
> >> Nothing wrong with a having a break IMHO.
>
> > My opinion is that there is everything wrong with
> > having a break. I don't think I have ever used one,
> > I write code that doesn't depend on that crutch.
>
> I guess its crutch-iness is in the eye of the beholder. You seem to have
> a dogmatic view about this.

No, it's just that the OP was asking whether
avoiding "while True" is considered Best Practice.
How can you answer such a question without sounding
dogmatic?

>
>
>
>
>
>
>
> >> while not done:
>
> >> seems very dangerous to me as you'd have to
>
> >> del done
>
> >> before writing the same construct again. That's the sort of thing that
> >> leads to errors.
>
> > Duh. I won't write silly code like that either.
> > If I need more than one loop structure then I'll
> > do something like
>
> > � � while not done_with_this
>
> > � � while not done_with_that
>
> This is neither clean or well scoped.
>
>
>
> > Besides, since I _always_ initialize the flag
> > before entering a loop, the flag can be reused
> > and doesn't have to be deleted (as long as the
> > loops aren't nested). And since I don't use goto,
> > there's no chance the initialization can be avoided.
>
> Initialising the flag is just another line of code that has to be
> interpreted later. I didn't notice the initialisation in your original post.

"Just another line that has to be interpreted later"
is a strange comment in the context of "del done".

>
>
>
> > The best way to avoid the pitfalls of spaghetti
> > code is to not write it in the first place.
>
> I agree. With 'break' it is obvious what the code does and there are
> fewer lines to write in the first place and comprehend in the second.

Do you consider Perl golf to be Best Practice?

John Reid

unread,
Oct 13, 2009, 12:11:02 PM10/13/09
to pytho...@python.org

Mensanator wrote:
> No, it's just that the OP was asking whether
> avoiding "while True" is considered Best Practice.
> How can you answer such a question without sounding
> dogmatic?

I was just pointing out your style of programming seems inflexible.

>
> "Just another line that has to be interpreted later"
> is a strange comment in the context of "del done".

Interpreted in the sense that the maintainer of the code interprets it,
not the machine.

Ethan Furman

unread,
Oct 13, 2009, 12:27:35 PM10/13/09
to pytho...@python.org
Mensanator wrote:
> On Oct 13, 3:44�am, John Reid <j.r...@mail.cryst.bbk.ac.uk> wrote:
>
>>while not done:
>>
>>seems very dangerous to me as you'd have to
>>
>>del done
>>
>>before writing the same construct again. That's the sort of thing that
>>leads to errors.
>>
>Duh. I won't write silly code like that either.
>If I need more than one loop structure then I'll
>do something like
>
>� � while not done_with_this
>
>� � while not done_with_that
>
>Besides, since I _always_ initialize the flag
>before entering a loop, the flag can be reused
>and doesn't have to be deleted (as long as the
>loops aren't nested). And since I don't use goto,
>there's no chance the initialization can be avoided.
>
>>Initialising the flag is just another line of code that has to be
>>interpreted later. I didn't notice the initialisation in your original post.
>
>
> "Just another line that has to be interpreted later"
> is a strange comment in the context of "del done".

I don't believe John is advocating using it, just pointing out that an
extra line is needed -- whether the extra line is "del loop_control_var"
or "loop_control_var = False", it's still an extra line.

Mind you, I'm not saying you should change the way you program as it
seems to work for you, just that there are other ways to write good
clean programs.

~Ethan~

Mensanator

unread,
Oct 13, 2009, 5:59:04 PM10/13/09
to

And I'm not saying John nor the OP should stop
using what works for them. But there are certainly
valid reasons for "don't use while True" to be
on the "Best Practices" list.

After all, how many times hve you put 'break'
in a loop comprehension?

>
> ~Ethan~

Mensanator

unread,
Oct 13, 2009, 6:02:09 PM10/13/09
to
On Oct 12, 4:59�pm, David C Ullrich <ullr...@math.okstate.edu> wrote:
> kj 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,
>
> Heh-heh: When I read this it occurred to me that another way to
> start an infinite loop would be to make a post here on this topic.
> Looking at the thread so far it appears I was right.

You're not getting away that easy.

What's YOUR opinion of "whilr True"?

Paul Rubin

unread,
Oct 13, 2009, 6:22:11 PM10/13/09
to
Mensanator <mensa...@aol.com> writes:
> And I'm not saying John nor the OP should stop using what works for
> them. But there are certainly valid reasons for "don't use while
> True" to be on the "Best Practices" list.
>
> After all, how many times hve you put 'break' in a loop
> comprehension?

<http://okmij.org/ftp/Streams.html#enumerator-stream>:

Towards the best collection traversal interface

"We present a design of the overall optimal collection traversal
interface, which is based on a left-fold-like combinator with
premature termination. The design has been implemented and tested in
practice."

Steven D'Aprano

unread,
Oct 13, 2009, 6:24:11 PM10/13/09
to
On Tue, 13 Oct 2009 14:59:04 -0700, Mensanator wrote:

> And I'm not saying John nor the OP should stop using what works for
> them. But there are certainly valid reasons for "don't use while True"
> to be on the "Best Practices" list.

"Valid"? Well, maybe. But none of them are convincing to me. The best I
have seen is that loops should have a single entry point and a single
exit point, to make it easier to reason about pre- and post-conditions.
But frankly I'm not convinced that's true -- or at least, multiple exists
shouldn't *necessarily* leader to difficulty in reasoning about the post-
condition.



> After all, how many times hve you put 'break' in a loop comprehension?

What's a loop comprehension?

Do you mean *list* comprehensions? List comps aren't supposed to be a
general purpose replacement for for-loops. They are a deliberately cut-
down version which is easier to read, write and execute than a pure
Python for-loop:

>>> from timeit import Timer
>>> Timer("""L = []
... for i in range(20):
... L.append(2*i-1)
... """, '').repeat()
[9.7169408798217773, 9.4620440006256104, 9.4636049270629883]
>>> Timer('[2*i-1 for i in range(20)]', '').repeat()
[5.6287829875946045, 5.8934588432312012, 5.7950780391693115]

But the consequence of that simplicity and speed is that they're not as
general as a for-loop. This was a design decision. But change the design
and you could have something like this:

[expr for name in seq until cond]

which breaks when cond becomes true.


--
Steven

Rhodri James

unread,
Oct 13, 2009, 6:38:56 PM10/13/09
to pytho...@python.org
On Tue, 13 Oct 2009 22:59:04 +0100, Mensanator <mensa...@aol.com> wrote:

> And I'm not saying John nor the OP should stop
> using what works for them. But there are certainly
> valid reasons for "don't use while True" to be
> on the "Best Practices" list.

Unfortunately, some of them seem to be reasons from
my point of view to put "*do* use while True" on the
"Best Practices" list. Some of the constructs you
seem to like ring big alarm bells with me, because
I've found entirely too many bugs hidden by them.

> After all, how many times hve you put 'break'
> in a loop comprehension?

How many times have you written 20-line list
comprehensions? If the answer is more than zero,
what on earth possessed you to think it was a
good idea? :-)

--
Rhodri James *-* Wildebeest Herder to the Masses