[comp.lang.c] new do-while syntax

johns@calvin.EE.CORNELL.EDU (John Sahr) (12/19/88)

In article <3049@arcturus> evil@arcturus.UUCP (Wade Guthrie) writes:
>In article <8536@alice.UUCP>, ark@alice.UUCP (Andrew Koenig) writes:
[suggesting a do-while syntax with the loop test in the middle]
>> 	do {
>> 		ch = getchar();
>> 	} while (ch != EOF) {
>> 		process(ch);
>> 	}
[deletions]
>                         ..........., but the above constructions
>are EXCEEDINGLY hard to read.  I much perfer the method which already
>exists:
>
>	while ( (c=getchar()) != EOF)
>		process(c);
>Wade Guthrie

I think the point of Mr. Koenig's proposal was to handle larger loops than
the literal interpretation of his example indicated.  Consider
>> 	do {
>> 		ch = getchar();
		ch &= MASK;
		ch  = table_look_up[ch];
		report_status(ch);
>> 	} while (ch != EOF) {
>> 		process(ch);
		process2(ch);
		process3(ch);
>> 	}

This too, is contrived, but is cleaner than jamming a bunch of statements
masquerading as an exit condition inside the test.
I'm not thrilled about the syntax, but it is an interesting idea.  It
adds no keywords, breaks no code, resembles if-else syntax, and would solve
some "artistic style" problems I run into.  Of course, one could use 
goto-labels, breaks, or that interesting switch-case-for loop that showed 
up in this group a while back.
Actually, my main objection with the syntax, I realize, is only the
indent/brace style, which differs from my own.  (I won't tread any further
along that path...:-) )

Happy Holidays,

John

-- 
John Sahr,                          School of Elect. Eng.,  Upson Hall   
                                    Cornell University, Ithaca, NY 14853

ARPA: johns@calvin.ee.cornell.edu; UUCP: {rochester,cmcl2}!cornell!calvin!johns

bph@buengc.BU.EDU (Blair P. Houghton) (12/19/88)

In article <864@calvin.EE.CORNELL.EDU> johns@calvin.ee.cornell.edu.UUCP (John Sahr) writes:
>>In article <8536@alice.UUCP>, ark@alice.UUCP (Andrew Koenig) writes:
>[suggesting a do-while syntax with the loop test in the middle]
>
>I think the point of Mr. Koenig's proposal was to handle larger loops than
>the literal interpretation of his example indicated.  Consider
>>> 	do {
>>> 		ch = getchar();
>		ch &= MASK;
>		ch  = table_look_up[ch];
>		report_status(ch);
>>> 	} while (ch != EOF) {
>>> 		process(ch);
>		process2(ch);
>		process3(ch);
>>> 	}
>
>This too, is contrived.

Pardon my two-cent kibbitz, but what's wrong with using the comma
operator to do that for which it is ideally suited?

I find the syntax as described above to be confusing.  All of the
"ch =" statements are in the do-while loop, and all of the "process()"
statements are subsequent to the loop, no?  No.  But it seems so.
(Unless of course I've got it exactly backwards; It Can Happen, especially
when I'm entering a discussion I just now discovered.)

The K&R-conformant version would be:

	do {
		process(ch);
		process2(ch);
		process3(ch);
	} while (
		ch = getchar(),
		ch &= MASK,
		ch  = table_look_up[ch],
		report_status(ch),
		ch != EOF
	);

See?  No muss, no fuss, sez who only curly-brackets get special
indentation, and you get to tell your grandchildren that you once
used the comma operator, which I consider one of the prime elegances
of the C language.

				--Blair
				  ",,,,"

ark@alice.UUCP (Andrew Koenig) (12/19/88)

In article <1716@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes:

> Pardon my two-cent kibbitz, but what's wrong with using the comma
> operator to do that for which it is ideally suited?

I can't use arbitrary statements with the comma operator:

	int i, status, count = 0;
	char temp[THINGSIZE];
	do {
		readthing(precious);
		++count;
		for (i = 0; i < THINGSIZE; i++)
			temp[i] = precious[i];
		status = munge(temp);
	} while (status) {
		for (i = 0; i < THINGSIZE; i++) {
			if (temp[i] != precious[i])
				printf ("munge changed element %d of line %d\n",
					i, count);
		}
	}

As I said before, it's way too late to get anything like this
into C now.  It's fun to think about, though.
-- 
				--Andrew Koenig
				  ark@europa.att.com

mikpe@mina.liu.se (Mikael Pettersson) (12/20/88)

In article <8562@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes:
>[edited]
>I can't use arbitrary statements with the comma operator:
>    do {
>	[read & munge & set status]
>    } while (status) {
>	for (i = 0; i < THINGSIZE; i++)
>	    if (temp[i] != precious[i])
>		printf ("munge changed element %d of line %d\n", i, count);
>    }

Watch:
     #include <setjmp.h>
     ...
     jmp_buf kappa;
     do {
	[read & munge & set status]
     } while(status &&
	      (i=0,
	       setjmp(kappa),
	       i<THINGSIZE &&
		 (temp[i]!=precious[i] &&
		    printf("munge changed element %d of line %d\n", i, count),
		  ++i,	
		  longjmp(kappa) ),
	       1 )
	    );

Compiles and runs just fine :-)

>As I said before, it's way too late to get anything like this
>into C now.  It's fun to think about, though.

Agreed.
BTW, I came up with the ideas for the above hack when I tried to figure out
a way to implement an `expression language' by translating it to plain old C.
It isn't pretty, but it would do if all you want is a quick and dirty
implementation of the new language.
-- 
Mikael Pettersson, Dept of Comp & Info Sci, University of Linkoping, Sweden
email: mpe@ida.liu.se  or  ..!{mcvax,munnari,uunet}!enea!liuida!mpe

peter@ficc.uu.net (Peter da Silva) (12/20/88)

In article <8562@alice.UUCP>, ark@alice.UUCP (Andrew Koenig) writes:
> As I said before, it's way too late to get anything like this
> into C now.  It's fun to think about, though.

Is it? Petition your compiler writer. It should be a completely safe and
transparent extension to the existing syntax. The following should all
be valid:

	do ... while(x);	/* existing do/while, null while expr */
	while(x) ...		/* existing while, null do expr */
	do ... while(x) ...	/* full do/while */

The yaccoid BNF would be (since ";" is a valid statement):

dowhile	:	do WHILE(expr) statement
	;

do	:	/* nothing */
	|	DO statement
	;

If you can get a few compiler writers to put this in, it'll have a chance
of making it to the next version of 'C'. It reduces the complexity of the
language, too... replaces three constructs (do, while, and for) with one.
(yes, I am aware of the 'continue' problem, and I'm not suggesting removing
the for statement).

In fact, this could be declared an "editorial change" if you have the
brass.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Work: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Home: bigtex!texbell!sugar!peter, peter@sugar.uu.net.

bph@buengc.BU.EDU (Blair P. Houghton) (12/21/88)

In article <8562@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes:
>In article <1716@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes:
>
>> Pardon my two-cent kibbitz, but what's wrong with using the comma
>> operator to do that for which it is ideally suited?
>
>I can't use arbitrary statements with the comma operator:

As others have recently reminded me, statement is not expression, and
expression is not statement.  The comma operator separates expressions
only.  My bad.

>As I said before, it's way too late to get anything like this
>into C now.  It's fun to think about, though.

But wait!  We could form a comittee, couldn't we?  We could be the
abCDE, and meet and review and vote and review and meet and field input
from the input field and meet, review, vote...

				--Blair
				  "...and end up with Fortro-C.scalispgol,
				   the scientific/systems/ai/graphic
				   programming language!  All things
				   to all people.  Damn the entropy!
				   Full redesign ahead!"

karl@haddock.ima.isc.com (Karl Heuer) (12/21/88)

In article <1724@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>In article <8562@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes:
>>As I said before, it's way too late to get anything like this into C now.
>
>But wait!  We could form a comittee, couldn't we?  We could be the
>abCDE, and meet and review and vote and review and meet and field input
>from the input field and meet, review, vote...

(Yes, I realize you were being sarcastic.  Nevertheless...)

Andrew is partially correct: it's way too late to get any fantastic new
features into C88 (__STDC__==1).  However, it is not too soon to be thinking
about what should go into C99 (__STDC__==2).  The correct procedure for such
future enhancements is to get them added as experimental extensions to
existing C compilers, so that the next ANSI C committee will have "existing
practice" to point to.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

seanf@sco.COM (Sean Fagan) (12/22/88)

In article <1716@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>In article <864@calvin.EE.CORNELL.EDU> johns@calvin.ee.cornell.edu.UUCP (John Sahr) writes:
>>>In article <8536@alice.UUCP>, ark@alice.UUCP (Andrew Koenig) writes:
>But what's wrong with [the following code]?
]	do {
]		process(ch);
]		process2(ch);
]		process3(ch);
]	} while (
]		ch = getchar(),
]		ch &= MASK,
]		ch  = table_look_up[ch],
]		report_status(ch),
]		ch != EOF
]	);

Uhm, little thinks like the fact that quite a few compilers will generate
the equivalent of:
	do {
		proces(ch);
		process2(ch);
		process3(ch);
	} while (
		getchar(), ch&MASK, table_look_op[ch], report_status(ch),
		ch != EOF)
	;

which is all that you're guarenteed (assuming the compiler does no
optimizations).  Put some optimizations in (assuming ch is non-volatile in
a dpANSI compiler, or the compiler assumes it isn't), and you get:

	getchar(), report_status(ch), ch!=EOF

as the conditional for the while.

Also, ch is not initialized to the getchar(), which it was in the initial
example (which I deleted, of course), and the code looks horrible.

Is that enough?

-- 
Sean Eric Fagan  | "Merry Christmas, drive carefully and have some great sex."
seanf@sco.UUCP   |     -- Art Hoppe
(408) 458-1422   | Any opinions expressed are my own, not my employers'.

stuart@bms-at.UUCP (Stuart Gathman) (12/22/88)

In article <8562@alice.UUCP>, ark@alice.UUCP (Andrew Koenig) writes:

> 	int i, status, count = 0;
> 	char temp[THINGSIZE];
> 	do {
> 		readthing(precious);
> 		++count;
> 		for (i = 0; i < THINGSIZE; i++)
> 			temp[i] = precious[i];
> 		status = munge(temp);
> 	} while (status) {
> 		for (i = 0; i < THINGSIZE; i++) {
> 			if (temp[i] != precious[i])
> 				printf ("munge changed element %d of line %d\n",
> 					i, count);
> 		}
> 	}

This is a necessary contruct.  In a structured assembler language I developed,
it goes like this:

	LOOP				REPEAT
		statements			statements
	WHILE	WHEN		or	UNTIL	WHEN
		statements			statements
	THEN 	cond			THEN	cond
	

The WHILE part was executed first.  *Any* condition could contain
a 'WHEN' clause.  (As in 'IF (A,LT,B),OR,WHEN . . .')

A generalized WHEN construct would be welcome in 'C'.  The specific
case being discussed, however, is handled quite well
by the break statement in standard 'C'!

	for (;;) {
	  c = getchar();
	  if (c == EOF) break;
	  process(c);
	}
-- 
Stuart D. Gathman	<stuart@bms-at.uucp>
			<..!{vrdxhq|daitc}!bms-at!stuart>

rogerson@PEDEV.Columbia.NCR.COM (rogerson) (12/22/88)

	Actor, an OOPS programming language for Microsoft Windows, uses
	the following construct for controlling loops:

		loop
		  ...
		while ( )
		  ...
		endloop

	To get the normal while-do or do-while it would look like:
		loop while ( )  /* while - do */
		  ...
		endloop
	and
		loop 		/* do - while */
		  ...
		while ( )
		endloop

	This is much more readable then the proposed C version, but then
	it would be incompatible with current C.

	A simple solution to the problem is to use a for statement and
	a break statement.  This is like Modula II which has the
	LOOP-EXIT-END control statement.

	-----Dale
		Rogerson-----

bph@buengc.BU.EDU (Blair P. Houghton) (12/23/88)

In article <1963@scolex> seanf@sco.COM (Sean Fagan) writes:
>In article <1716@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
[in response to:]
>>>>In article <8536@alice.UUCP>, ark@alice.UUCP (Andrew Koenig) writes:
>>But what's wrong with [the following code]?
>>	do {
>>		process(ch);
>>		process2(ch);
>>		process3(ch);
>>	} while (
>>		ch = getchar(),
>>		ch &= MASK,
>>		ch  = table_look_up[ch],
>>		report_status(ch),
>>		ch != EOF
>>	);
>
>Uhm, little thinks like the fact that quite a few compilers will generate
>the equivalent of:

[...broken code deleted...]
Buy yerself a new compiler.  This one's screwed.

[...optimization of broken code deleted quickly...]
>Also, ch is not initialized to the getchar(), which it was in the initial
>example (which I deleted, of course), and the code looks horrible.

I happen to think it looks just fine; the usage of "(" and ");" parallels
the usage of "{" and "}", and the comma is akin to a sort of sub-semicolon.
(Will the Semanticists please put away those rotten vegetables?  Thank you.)

It Just Ain't C.

>Is that enough?

No, you forgot to impugn my ancestry.

And to mention that statement is not expression, expression is not
statement.  The example above is not complete by any means, and will
break if I try to put a "for(expr;expr;expr);," in the middle of the
while-block.

				--Blair
				  "...something about..."

dhesi@bsu-cs.UUCP (Rahul Dhesi) (12/23/88)

If we're really redesigning the language, a single general construct
suffices:

     do
       ...  /* zero or more statements */
       while condition
       ...  /* zero or more statements */
     done
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee}!bsu-cs!dhesi

denbeste@bgsuvax.UUCP (William C. DenBesten) (12/23/88)

How 'bout something simple that works _now_?

#define loop for(;;)
#define exitif(a) if (a) break

main()
{
  char ch;
  loop {
    ch = getchar();
    exitif (ch==EOF);
    putc(ch);
  }
}

This seems much less prone to a missing semi-colon causing a really nasty
error. IMHO, this is much easier to follow than do{}while(){};.

-- 
          William C. DenBesten |       denbeste@bgsu.edu
      Dept of Computer Science | CSNET denbeste%andy.bgsu.edu@relay.cs.net
Bowling Green State University | UUCP  ...!osu-cis!bgsuvax!denbeste
  Bowling Green, OH 43403-0214 |

gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/27/88)

In article <3317@bgsuvax.UUCP> denbeste@bgsuvax.UUCP (William C. DenBesten) writes:
>#define exitif(a) if (a) break

Doesn't work (exercise for the student).
Also, recall the earlier discussion about Bourne's Algolish C macros.

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

This do-while-done loop syntax is exactly what forth uses - and I always
thought C was 'higher' level than Fourth :-)

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