Is it okay if I use a lot of while(true) loops?

P

Pavel

tni said:
No, you haven't. It's almost always used in conjunction with break (real
infinite loops are quite rare). This pattern is so common that that Qt
has a special keyword 'forever'.
Lots of languages have special native keywords for forever loops. REXX
and PL/1, just to give a couple of examples.
 
P

Pavel

Daniel said:
There are situations where while(true) is appropriate, but I can't
accept your reason for using it. If you had said you were using it to
reduce duplication of code, then sure, but not just because you happen
to find it more comfortable.
I believe there is no right answer. It depends on how the potential
reader's brains are wired and that probably in turn depends on his/her
background. Personally I started with FORTRAN 66 and Assembler so I
always mentally decompose any funky control instruction into test and
branch or equivalent CPU commands. When I was introduced to PL/1 first
thing I did was to mentally implement all its reach set of flow control
instructions in terms of GOTOs and IF-GOTOs :). Some of those turned
out to be clearer than their "higher level" equivalents.

I think sometimes it's even objectively beneficial to look at the code
this way as you can guess the machine code to be generated and get a
better idea on its performance (how much forward-vs-backward branching
the code will create etc). Of course I admit it's not everybody's
day-to-day job...

-Pavel
 
P

Pavel

Daniel said:
There are situations where while(true) is appropriate, but I can't
accept your reason for using it. If you had said you were using it to
reduce duplication of code, then sure, but not just because you happen
to find it more comfortable.

I believe there is no right answer. It depends on how the potential
reader's brains are wired and that probably in turn depends on his/her
background. Personally I started with FORTRAN 66 and Assembler so I
always mentally decompose any funky control instruction into test and
branch or equivalent CPU commands. When I was introduced to PL/1 first
thing I did was to mentally implement all its reach set of flow control
instructions in terms of GOTOs and IF-GOTOs :). Some of those turned
out to be clearer than their "higher level" equivalents.

I think sometimes it's even objectively beneficial to look at the code
this way as you can guess the machine code to be generated and get a
better idea on its performance (how much forward-vs-backward branching
the code will create etc). Of course I admit it's not everybody's
day-to-day job...

-Pavel
 
F

Francesco S. Carta

on 21/08/2010 said:
I guess because it's not equivalent: your code would doCommand() even if
cmd == exitCmd and Francesco's code wouldn't;

Just for the records, I posted no code in this thread; that was Alf's code.
 
T

tni

Why not:

Command cmd = restCmd; // or where is that cmd declared?
while( cmd != exitCmd )
{
showGameState();
cmd = usersCommand();
doCommand( cmd );
}

To begin with, your code is buggy. Once you fix that, you have code
duplication.

You have introduced a dummy command that doesn't really serve a
meaningful purpose, needs to be documented and tested. That dummy
command is a special case, so you probably want to test everything
dealing with commands for that case.

To 'improve' a local issue, you have introduced global complexity.
 
P

Pavel

Francesco said:
Just for the records, I posted no code in this thread; that was Alf's code.
Sorry, my fault. My reader got messed up; that's why I double-posted
once today, too. I think I have fixed it.
-Pavel
 
Ö

Öö Tiib

To begin with, your code is buggy. Once you fix that, you have code
duplication.

That is unclear what is buggy there. exitCmd is not handled by
doCommand in original, instead it is handled sort of outside ...
globally. Crap had leaked out of its locality before me. That sort of
confused me. I even commented it with question in code.

Where your non-buggy design puts the usual quit handling? "Are you
sure to quit? Do you maybe want to save?" I would prefer them in
doCommand().
You have introduced a dummy command that doesn't really serve a
meaningful purpose, needs to be documented and tested. That dummy
command is a special case, so you probably want to test everything
dealing with commands for that case.

To 'improve' a local issue, you have introduced global complexity.

Usually there are 3 states when game ends: player lost, player won or
player quit playing. So life is more complex. I did introduce nothing.
You did introduce lot of nonsense, like there was some sort of design
that i terribly violated and broke.

Show me the spec that say that my restCmd is a dummy one? So your
whole accusation is based on my violation of unexisting things.
 
P

Phlip

In my code I usually find it much simpler to use a while(true) (or
do ... while(true)) loop instead of putting a real condition, and make
a test inside the body of the loop. Usually I find it much more
comfortable to check manually.

So, if you were reading my code, would you dislike this?

A best way to break out of such loops is with return. That forces your
methods to remain short.
 
J

joe

Alexander wrote:

"Is it okay if I use a lot of while(true) loops?".

If you have a fetish for compiler warnings, go for it!
 
A

Alf P. Steinbach /Usenet

* Öö Tiib, on 22.08.2010 04:09:
That is unclear what is buggy there. exitCmd is not handled by
doCommand in original, instead it is handled sort of outside ...
globally. Crap had leaked out of its locality before me. That sort of
confused me. I even commented it with question in code.

"Exit" is a special command because it needs handling at the level that calls
'doCommand'. That level has to stop looping. In your code you're thinking about
'doCommand' perhaps asking the user to confirm, but you stop looping anyway...

So, you can either special-case the signature of 'doCommand' to support "Exit",
or you can just handle it directly. Special-casing is problematic because there
can be two or three such special cases.

It's the KISS principle, Keep It Simple.

You might alternatively consider the weaker example


double sum = 0.0;

cout << explanation << endl;
for( ;; )
{
double const number = numberFromUser( "Number? " );

if( number == 0.0 ) { break; }
sum += number;
}


But in a way it accentuates the issue because here it's a least plausible to put
both the input operation and checking as a 'while' loop condition.

To my eyes the 'while', with side-effect condition, obfuscates what the effect
of the code is, sort of compiling it down to a lower level language, needlessly
extends the scope of a variable, and makes it more difficult to introduce
changes, i.e. reduced maintainability.


Cheers & hth.,

- Alf
 
P

Phlip

The loop-and-a-half practice is common enough that no one should
have difficulty reading it. Unless, of course, the loop is HUGE

....then Method Object Refactor it.
 
J

James

tni said:
No, you haven't. It's almost always used in conjunction with break (real
infinite loops are quite rare). This pattern is so common that that Qt has
a special keyword 'forever'.

#define forever for (;;)

forever {
/* do something */
}

lol
 
P

Phlip

Yes:).  In fact, of course, anything we say about a program (in
the code), is contingent on many external conditions: that the
system doesn't crash, that no one unplugs the machine, etc.  But
this is (or should be) understood.  For that matter, in most
contexts, "while (true)" admits that the loop may be broken by
means of an assertion failure, or even an exception.  It's just
a statement about normal program flow.

Stated positively, let's replace while(true) with while(activating()),
where the activating() method (under a better name) contains whatever
the top half of the loop was doing.

If your code is not so easy to morph into sufficient self-
documentation to appease Kanze, then you have bigger problems than a
while(true)!
 
P

Phlip

   for( ;; )
   {
       showGameState();
       cmd = usersCommand();
       if( cmd == exitCmd ) { break; }
       doCommand( cmd );
   }

But that satisfies the "forever" concept. (Watch the average modern
game player for a few hours to see what I mean ;)
 
Ö

Öö Tiib

* Öö Tiib, on 22.08.2010 04:09:





"Exit" is a special command because it needs handling at the level that calls
'doCommand'. That level has to stop looping. In your code you're thinking about
'doCommand' perhaps asking the user to confirm, but you stop looping anyway...

Yes, that was that command with what i was confused.
So, you can either special-case the signature of 'doCommand' to support "Exit",
or you can just handle it directly. Special-casing is problematic because there
can be two or three such special cases.

It's the KISS principle, Keep It Simple.

Ok lets try to KISS ... how about like that:

initGame();
do
{
showGameState();
Command cmd = usersCommand();
doCommand( cmd );
}
while( !gameOver() ); // player did exit, lose or win

You might alternatively consider the weaker example

     double  sum     = 0.0;

     cout << explanation << endl;
     for( ;; )
     {
         double const number = numberFromUser( "Number? " );

         if( number == 0.0 ) { break; }
         sum += number;
     }

But in a way it accentuates the issue because here it's a least plausible to put
both the input operation and checking as a 'while' loop condition.

To my eyes the 'while', with side-effect condition, obfuscates what the effect
of the code is, sort of compiling it down to a lower level language, needlessly
extends the scope of a variable, and makes it more difficult to introduce
changes, i.e. reduced maintainability.

Yes it is perhaps better example.
 
T

tni

First real infinite loops aren't that rare; they occur more
often than you'd suspect.

Really? You can only execute 1 per thread, so how many are you going to
have in any given application (I highly doubt it's more than a handful)?

Things like 'loop and a half' and loops with complex exit conditions
where break simplifies things are orders of magnitude more common (of
course, I haven't worked in any environment where break was banned).
 
J

Juha Nieminen

James Kanze said:
And second, using break later in the
loop, rather than stating the conditions up front, at the top,
is obfuscation.

While definitely not extremely common, it's not unusual that the
condition to terminate the loop needs to be calculated inside the
loop first, before it can be decided whether the loop should terminate
or not. Sometimes you can do that with a do...while() loop, but it also
often happens that you need to do things *after* the termination condition
has been determined, in which case a do...while() can't be used. (In my
experience this situation is actually more common than the situations
where do...while() can be used.)

In most such cases you can try to rearrange the program in such way
that the condition is calculated and stated somehow in the 'while'
statement itself, but this often makes the code more complicated than
the simpler version using a 'break' in the middle of the loop body
would be. Forcing yourself to avoid 'break' at all costs will, in fact,
sometimes make your code more complicated than it needs to be. (And note
that I already said this situation is "definitely not extremely common",
so please don't nitpick on that.)
 
D

Daniel

I believe in writing clean, easily
understood code.  Using break in the middle of a loop is not
clean, easily understood code.  

The alternatives commonly are

(i)

bool done = false;
while (!done)
{
// Some code that returns a result
if (result)
{
done = true;
}
else
{
// Some more code
}
}

versus

(ii)

while (true)
{
// Some code that returns a result
if (result)
{
break;
}
// Some more code
}

I find it hard to see that (ii) is less clear. In both cases, the
logic for stopping is in the body of the code, and (i) is more
compact.

-- Daniel
 
J

Juha Nieminen

Daniel said:
bool done = false;
while (!done)
{
// Some code that returns a result
if (result)
{
done = true;
}
else
{
// Some more code
}
}

You could always do it like:

while(codeThatReturnsAResult() &&
someMoreCodeWhichAlwaysReturnsTrue())
{}

and implement those functions appropriately (passing all necessary local
variables as references, as necessary).

Now you have the ending condition nicely in the while loop. And as a
bonus, your code is significantly more obfuscated and harder to follow.
 

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,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top