Suggested new C loop syntax

Mark A Terribile mat at mole-end.UUCP
Mon Jan 2 13:10:30 AEST 1989


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



More information about the Comp.lang.c mailing list