[comp.lang.c] Suggested new C loop syntax

bill@twwells.uucp (T. William Wells) (12/22/88)

In article <2485@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
: In article <3049@arcturus>, evil@arcturus.UUCP (Wade Guthrie) writes:
: > In article <8536@alice.UUCP>, ark@alice.UUCP (Andrew Koenig) writes:
: > >   do      ch = getchar();
: > >   while (ch != EOF)
: > >           process(ch);
: > > or, with braces:
: > >   do {
: > >           ch = getchar();
: > >   } while (ch != EOF) {
: > >           process(ch);
: > >   }
:
: This is a wonderful and clean extension to 'C' that solves the loop problem
: once and for all!

This is a bad syntax.

Why?

Because of this:

	do
		statement
	while (expr);
		statement

See the difference? Well, in case you didn't, it is the semicolon at
the end of the while expression. This is damned hard to spot and does
not lead to a syntax error.

I'll stick to using a break.

---
Bill
{uunet|novavax}!proxftl!twwells!bill

fnf@estinc.UUCP (Fred Fish) (12/23/88)

In article <264@twwells.uucp> bill@twwells.UUCP (T. William Wells) writes:
<: < In article <8536@alice.UUCP<, ark@alice.UUCP (Andrew Koenig) writes:
<: < <   do {
<: < <           ch = getchar();
<: < <   } while (ch != EOF) {
<: < <           process(ch);
<: < <   }
<
<	do
<		statement
<	while (expr);
<		statement
<
<See the difference? Well, in case you didn't, it is the semicolon at
<the end of the while expression. This is damned hard to spot and does
<not lead to a syntax error.

Since this is my pet peeve #1 about C style, I couldn't resist.  There
is no ambiguity if you simply make it a habit to ALWAYS include braces
for {if, while, do, for} etc, even when they are not strictly necessary.

I was recently helping out a freshman CS major with her C homework and
found out, to my horror, that the teacher in the course was marking
off points for code which included braces when they weren't strictly
required.  They were teaching her to write code like:

	inchar = getchar ();
	while (inchar != EOF)
		if (inchar == 0)
			goto done;
		else
			inchar = getchar ();
done:	return inchar;

Ickkk!!!
-Fred
-- 
# Fred Fish, 1346 West 10th Place, Tempe, AZ 85281,  USA
# asuvax!nud!fishpond!estinc!fnf          (602) 921-1113

jfc@athena.mit.edu (John F Carr) (12/23/88)

In article <264@twwells.uucp> bill@twwells.UUCP (T. William Wells) writes:
>This is a bad syntax.
>	do
>		statement
>	while (expr);
>		statement
>
>See the difference? Well, in case you didn't, it is the semicolon at
>the end of the while expression. This is damned hard to spot and does
>not lead to a syntax error.

Do you never use loops in C?  If you do, you are vulnerable to the same
mistake regardless of which variety you use.

  while(expr);
     statement

and

  for(;;);
   
are legal under the current C standard.  I do not see how the proposed 
extension creates any new potential for failure.  

--
   John Carr             "When they turn the pages of history,
   jfc@Athena.mit.edu     When these days have passed long ago,
   bloom-beacon!          Will they read of us with sadness
   athena.mit.edu!jfc     For the seeds that we let grow?"  --Neil Peart

mat@mole-end.UUCP (Mark A Terribile) (01/02/89)

> >This is a bad syntax.
> >	do
> >		statement
> >	while (expr);
> >		statement
> >
> >... in case you didn't, it is the semicolon at the end of the while
> >expression. This is damned hard to spot and does not lead to a syntax error.
> 
> Do you never use loops in C?  If you do, you are vulnerable to the same
> mistake regardless of which variety you use.
> 
>   while(expr);
>      statement

It's not quite as bad.  Before the extensions, you can take some precautions.

Never use the null statement as the body of a loop.  Instead, use  {}  or
{ /* Null */ }  .  For the do-while, put the while on the same line as the
``}'' of the loop, and never write the body without the braces.  Then you at
least know that any  while();  or  for(;;);  is an error.  (I don't like the
``continue'' in this role because it's a statement with a real meaning, which
meaning happens to produce null effect in this one case.)

After the extensions, if you see a  do{ }while();  you cannot be sure whether
the following statement should be part of the loop or not.  ``But if it's a
compound ...?''  Not good enough.  Compound statements are also written to
create a lexical scope for variables that are needed over just a few
statements, and I argue that it is good style to write code that way.  ``Use
K&R braces for control flow and {-over-} for lexical scope.''  I suppose, but
this is really stretching it.

There is another reason to ask if this construction is a good one.  Both the
test-at-the-top and test-at-the-bottom assume that there is one place to write
the loop control.  This new version is an attempt to accommodate the ``classical
loop-and-a-half.''  What is the loop-and-a-half?  Just a loop in which you
have to try some stuff before you can do the loop test.  In C, you can often
push that stuff off into the test-expression of the for(;;) or while() .
(In Pascal, it's virtually impossible unless you write boolean functions for
everything, which is why Pascal code needs so many loop*3/2's--and why it hurts
so much not to be able to write them.)  But sometimes the loop-and-a-half
idiom has to be repeated several times in the course of one loop:

	for( n_compacted = 0 ; p ; p = p->next, n_compacted++ )
	{
		p->type = reduce( p->type );
		if( p->type != p->back->type )
			break;

		if( n_compacted >= NODE_MAX )
		{
			. . . start new node anyway . . .
		}

		if(    p->left
		    && COMPLEX( reduce( p->left->type )
		 ||    p->right
		    && COMPLEX( reduce( p->right->type ) )
		{
			p->flags |= CHECK_DESCENDANTS;
			break;
		}

		. . .
	}

I think you see the picture.  The new syntax helps such cases not at all.
You don't want to use the while() for one of the N tests because it emphasizes
one at the expense of the others.  Nor does it seem sensible to try to
extend the syntax from one to N, and code which was written using the new
syntax would have to be rewritten when N became greater than one.  Worse, it
might not be rewritten, either out of misplaced respect for the author of the
code, out of misunderstanding of what was happening, out of management
directives that called for ``minimal change'' rather than ``appropriate
change'', or any number of other reasons, inertia not the least among them.

This leads me to conclude that use of the proposed (extended) construction
would be Bad Practice, and that the construction would be A Bad Thing.
-- 

(This man's opinions are his own.)
From mole-end				Mark Terribile

maujt@warwick.ac.uk (Richard J Cox) (01/10/89)

In article <264@twwells.uucp> bill@twwells.UUCP (T. William Wells) writes:
(stuff deleted)
>
>	do
>		statement
>	while (expr);
>		statement
>
>See the difference? Well, in case you didn't, it is the semicolon at
>the end of the while expression. This is damned hard to spot and does
>not lead to a syntax error.
>
>I'll stick to using a break.
>
>---
>Bill
>{uunet|novavax}!proxftl!twwells!bill

This is exactly the same as:

for(expr; expr; expr);
	statment

which every C programmer has to be able to spot anyway - so whats the problem?




- RC

/*--------------------------------------------------------------------------*/
JANET:  maujt@uk.ac.warwick.cu     BITNET:  maujt%uk.ac.warwick.cu@UKACRL
ARPA:   maujt@cu.warwick.ac.uk	   UUCP:    maujt%cu.warwick.ac.uk@ukc.uucp
Richard Cox, 84 St. Georges Rd, Coventry, CV1 2DL; UK PHONE: (0203) 520995