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