[net.lang.c++] Unintuitive semantics for initializing in for statements

sher@rochester.ARPA (David Sher) (04/14/86)

I have been trying to write an application in c++ (a simple parser
for slot filler files).  I have run into various problems but the one
that I think is obviously wierd is the semantics of initializing 
in the for statement.  Basically my gripe is that:
#include <stream.h>
void
main()
    {
    for ( int i = 0 ; i < 3 ; i++ ) cout << "Print me\n";
    for ( int i = 0 ; i < 3 ; i++ ) cout << "Print me\n";	// error
    }

Causes an error on the line labelled error.  

I would naturally expect
the scope of a variable defined in a for statement to last for
the rest of the for statement not for the rest of the enclosing
function as it does now.  This scoping makes it somewhat hard 
to define generic iterating code (one would have to enclose the
for statement in a block.  Just put it on my wish list for the 
next eddition.  (unfortunately some yangs out there may already have
used this misfeature in their programs by then!)

To prevent useless replies, yes I know that this behavior is consistent
with the book, I just wish it wasn't.
-- 
-David Sher
sher@rochester
seismo!rochester!sher

shopiro@alice.UucP () (04/21/86)

The advantage in having the iteration variable declared in a for
statement remain accessible is that you can test its value after
the end of the loop.

		-- Jonathan Shopiro

kwh@bentley.UUCP (KW Heuer) (04/23/86)

In article <5334@alice.uUCp> alice!shopiro (Jonathan Shopiro) writes:
>The advantage in having the iteration variable declared in a for
>statement remain accessible is that you can test its value after
>the end of the loop.

True, although I seldom (if ever) use it -- if it was a simple counting
loop as in the example, I already know the terminating value unless a
break statement was reached ("for (i=0; i<N; ++i) if (a[i]==X) break;"),
and I find that type of code ugly because it usually has to be followed
by a second test of the same condition ("if (i<N)...; else notfound();").
I much prefer "for (i=0; i<N; ++i) if (a[i]==X) return i; return NONE;"
which can be nicely embedded in a routine of its own.  (Perhaps the newer
compilers can even code it inline?  The last one I saw couldn't handle
loops in an inline function.)  But I digress.

I support the idea of having the interation variable go out of scope at
the end of the for statement.  It makes sense, since it was declared as
part of that statement.  (Yes, the alternative also makes sense because
of the definition of "for".)  I would find it quite useful.  For those
cases where I need the value outside the for, I'd prefer to declare the
variable outside anyway.

One last point.  If the compiler knows that the control variable is out
of scope after the loop, and is not modified within the loop, some neat
optimizations may be possible.  This is not too useful for the compilers
that generate C output, but may be of interest for implementations that
generate assembly language.

Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint

rlb@zaiaz32.UUCP (04/27/86)

> The advantage in having the iteration variable declared in a for
> statement remain accessible is that you can test its value after
> the end of the loop.
> 
> 		-- Jonathan Shopiro

    As has been pointed out, the following construct commonly appears
in coding:
		for(i = 0; i < MAX_I; ++i)
			{
			    .
			    .
			    .
			}
		if(i >= MAX_I)
			<code 'cause FOR loop "fell through">

In the true spirit of language diddling, how about allowing "else"
statements to bind with "for"s as well as "if"s?  The "else" of
a "for" would be taken if the loop terminated "naturally".  That is,
the "else" of a "for" would be skipped if the loop was exited by means
of a "break" statement.  Of course, once you allow "for"s to have "else"s,
why deprive "while"s, and "do-while"s?  This is not a tenable solution
in C++, since it would break some existing C programs (unless "else"s bound
to "if"s more strongly than they did to "for"s :-)  Just a thought.  Pros?
Cons?  Gut-level feelings of revulsion?

{ihnp4|akgua|nsc}!zaiaz!rlb		-Ron Burk

db@cstvax.UUCP (Dave Berry) (04/28/86)

In article <5334@alice.uUCp> shopiro@alice.UUCP writes:
>The advantage in having the iteration variable declared in a for
>statement remain accessible is that you can test its value after
>the end of the loop.

An alternative would be to have a 'for' expression - the same as a 'for'
statement except that it returns the value of the iteration variable on
exit.  This satisfies your requirement to have such information available
while also avoiding the unintuitive behaviour noted by the original poster.

Mind you, I'm not convinced that the value of an iteration variable is needed
often enough in time-critical code for either system to be required.  An 
assignment in the loop body will give this info when its needed.
-- 
	Dave Berry. CS postgrad, Univ. of Edinburgh		
					...mcvax!ukc!cstvax!db

anw@nott-cs.UUCP (04/29/86)

In article <101@cstvax.UUCP> db@cstvax.UUCP (Dave Berry) writes:
> An alternative would be to have a 'for' expression - the same as a 'for'
> statement except that it returns the value of the iteration variable on
> exit.

	The trouble with all such suggestions is that there are too many
things that a loop *could* deliver, and for every application that would
make use of one such thing, there are equally worthy applications for all
the others.  Further, there is always a cogent objection.  For example,
you could return:

   a)	The value that the iteration variable would have on the next cycle
	[ie, the value that caused termination] -- but this could easily
	be > maxint.
   b)	The value it did have on the last cycle -- but there might not
	have been one.
   c)	The number of cycles -- but this could easily be > maxint [well,
	fairly easily].
   d)	Whatever the last obeyed controlled statement delivered -- but
	there might not have been one.
   e)	The collection of objects delivered by the controlled statements
	-- nice, but doesn't half fill up the stack!
   f,g,h,...)	Add to taste, depending on your favoured language.

	Better to have nothing than to spread such confusion!

							-- Andy Walker.

mayer@rochester.ARPA (Jim Mayer) (05/05/86)

Several notes have mentioned using loop variables after the loop as
a reason for making:

	for (int i = ...)

equivalent to

	int i;
	for (i = ...)

It seems to me that if the loop variable is really needed after
the "for" statement, then the second form is just about as easy to
write and expresses the use of the variable much more clearly.

I consider the current semantics a real wart.  Actually, after programming
fairly intensively in C++ for a month or so, I feel that scoping in general
is the single weakest point of the language.  The way enumeration types
(and constants in general) are handled within classes is particulary
poor.  Are the scope issues going to be addressed more fully in
subsequent releases?

-- Jim Mayer					University of Rochester
(arpa) mayer@Rochester.ARPA			Department of Computer Science
(uucp) rochester!mayer				Ray P. Hylan Building
       (via allegra, decvax, or seismo)		Rochester, New York 14627

kwh@bentley.UUCP (KW Heuer) (05/10/86)

In article <224@tuck.nott-cs.UUCP> nott-cs!anw (Andy Walker) writes:
>In article <101@cstvax.UUCP> db@cstvax.UUCP (Dave Berry) writes:
>> An alternative would be to have a 'for' expression - the same as a 'for'
>> statement except that it returns the value of the iteration variable on
>> exit.

Not all "for" statements *have* an iteration variable.

>	The trouble with all such suggestions is that there are too many
>things that a loop *could* deliver, and for every application that would
>make use of one such thing, there are equally worthy applications for all
>the others.  Further, there is always a cogent objection.  For example,
>you could return:
>
>   a)	The value that the iteration variable would have on the next cycle
>	[ie, the value that caused termination] -- but this could easily
>	be > maxint.

If so, you've already got a problem (probably infinite loop).  Remember, a
"for" is just a glorified "while".

>...	Better to have nothing than to spread such confusion!

I ran into these same problems some years ago when designing a language with
statement-expression equivalence.  I concluded that a loop has a void value.

In C++, it's not so bad having statements which are not expressions, because
you can just make a one-statement inline function and use "return".

Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint

peter@baylor.UUCP (05/10/86)

> the "else" of a "for" would be skipped if the loop was exited by means
> of a "break" statement.  Of course, once you allow "for"s to have "else"s,
> why deprive "while"s, and "do-while"s?  This is not a tenable solution
> in C++, since it would break some existing C programs (unless "else"s bound
> to "if"s more strongly than they did to "for"s :-)  Just a thought.  Pros?
> Cons?  Gut-level feelings of revulsion?

I like it, however the semantics of the statement don't quite gibe with
the syntax if you use it the way you describe. How about this equivalence?

New Syntax		Equivalent Code (except for evaluations):

while(e)		if(e)
	s1			while(e)
else					s1
	s2		else
				s2

for(i; e; i)		i;
	s1		if(e)
else				for(; e; i)
	s2				s1
			else
				s2

...and so on. Of course, this doesn't address the problem of the value of
the iteration variable. Personally, I prefer to be able to test the value
of that variable directly. Of course I usually make my iteration variables
registers anyway, since most of the code I write these days is real-time
stuff...
-- 
-- Peter da Silva
-- UUCP: ...!shell!{baylor,graffiti}!peter; MCI: PDASILVA; CIS: 70216,1076

peter@baylor.UUCP (Peter da Silva) (05/15/86)

> In article <224@tuck.nott-cs.UUCP> nott-cs!anw (Andy Walker) writes:
> >In article <101@cstvax.UUCP> db@cstvax.UUCP (Dave Berry) writes:
> >> An alternative would be to have a 'for' expression - the same as a 'for'
> >> statement except that it returns the value of the iteration variable on
> >> exit.
> 
> Not all "for" statements *have* an iteration variable.
> 
> In C++, it's not so bad having statements which are not expressions, because
> you can just make a one-statement inline function and use "return".

How about going back to BCPL and allow *any* block to have a value that is
returned by "return" (or use the BCPL keyword "resultis")?

I have a question about C++: what is "cout << value"? I presume that's
supposed to print the value in an appropriate format, but I can't figure
why "cout". Why not "print value..."?
-- 
-- Peter da Silva
-- UUCP: ...!shell!{baylor,graffiti}!peter; MCI: PDASILVA; CIS: 70216,1076

kwh@bentley.UUCP (KW Heuer) (05/19/86)

In article <652@baylor.UUCP> baylor!peter (Peter da Silva) writes:
[bentley!kwh writes:]
>>In C++, it's not so bad having statements which are not expressions, because
>>you can just make a one-statement inline function and use "return".
>
>How about going back to BCPL and allow *any* block to have a value that is
>returned by "return" (or use the BCPL keyword "resultis")?

I think it's obvious why you couldn't use "return".  As for the BCPL-style
"valof ... resultis", I think the inline function is a simpler concept (and
it looks cleaner besides).

>I have a question about C++: what is "cout << value"? I presume that's
>supposed to print the value in an appropriate format, but I can't figure
>why "cout". Why not "print value..."?

It isn't a builtin.  "cout" and this interpretation of "<<" are defined in
"stream.h".  "cout" corresponds to "stdout"; you can have other streams.

Karl W. Z. Heuer (ihnp4!bentley!kwh), The Walking Lint