Are "while(true)" loops so bad? [closed]

I've been programming in Java for several years now, but I just recently returned to school to get a formal degree. I was quite surprised to learn that, on my last assignment, I lost points for using a loop like the one below.

do{
     //get some input.
     //if the input meets my conditions, break;
     //Otherwise ask again.
} while(true)

Now for my test I'm just scanning for some console input, but I was told that this kind of loop is discouraged because using break is akin to goto, we just don't do it.

I understand fully the pitfalls of goto and its Java cousin break:label, and I have the good sense not to use them. I also realize that a more complete program would provide some other means of escape, say for instance to just end the program, but that wasn't a reason my professor cited, so...

What's wrong with do-while(true)?


I wouldn't say it's bad - but equally I would normally at least look for an alternative.

In situations where it's the first thing I write, I almost always at least try to refactor it into something clearer. Sometimes it can't be helped (or the alternative is to have a bool variable which does nothing meaningful except indicate the end of the loop, less clearly than a break statement) but it's worth at least trying.

As an example of where it's clearer to use break than a flag, consider:

while (true)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        break;
    }
    actOnInput(input);
}

Now let's force it to use a flag:

boolean running = true;
while (running)
{
    doStuffNeededAtStartOfLoop();
    int input = getSomeInput();
    if (testCondition(input))
    {
        running = false;
    }
    else
    {
        actOnInput(input);
    }
}

I view the latter as more complicated to read: it's got an extra else block, the actOnInput is more indented, and if you're trying to work out what happens when testCondition returns true, you need to look carefully through the rest of the block to check that there isn't something after the else block which would occur whether running has been set to false or not.

The break statement communicates the intent more clearly, and lets the rest of the block get on with what it needs to do without worrying about earlier conditions.

Note that this is exactly the same sort of argument that people have about multiple return statements in a method. For example, if I can work out the result of a method within the first few lines (e.g. because some input is null, or empty, or zero) I find it clearer to return that answer directly than to have a variable to store the result, then a whole block of other code, and finally a return statement.


AFAIK nothing, really. Teachers are just allergic to goto, because they heard somewhere it's really bad. Otherwise you would just write:

bool guard = true;
do
{
   getInput();
   if (something)
     guard = false;
} while (guard)

Which is almost the same thing.

Maybe this is cleaner (because all the looping info is contained at the top of the block):

for (bool endLoop = false; !endLoop;)
{

}

Douglas Crockford had a remark about how he wished JavaScript contained a loop structure:

loop
{
  ...code...
}

And I don't think Java would be any worse for having a loop structure either.

There's nothing inherently wrong with while(true) loops, but there is a tendency for teachers to discourage them. From the teaching perspective, it's very easy to have students create endless loops and not understand why the loop isn't ever escaped.

But what they rarely mention is that all looping mechanisms can be replicated with while(true) loops.

while( a() )
{
  fn();
}

is the same as

loop
{
  if ( !a() ) break;
  fn();
}

and

do
{
  fn();
} while( a() );

is the same as:

loop
{
  fn();
  if ( !a() ) break;
}

and

for ( a(); b(); c() )
{
  fn();
}

is the same as:

a();
loop
{
  if ( !b() ) break;
  fn();
  c();
}

As long as you can set up your loops in a way that works the construct that you choose to use is unimportant. If it happens to fit in a for loop, use a for loop.

One last part: keep your loops simple. If there's a lot of functionality that needs to happen on every iteration, put it in a function. You can always optimize it after you've got it working.