[comp.lang.c++] scope of FOR

ron@hcr.UUCP (Ron Irvine) (08/22/89)

The expansion of the FOR statement in C++ is great.
Being able to say "for(int i=0; i<100; ++i) ... " is
just what I want when I am coding a loop.  However, I
could not believe that C++ has defined the scope of the
declared name (i in this case) to be "to the end of the
block enclosing the for-statement" (pg. 294, of The C++
programming language).

One problem with the current definition is that it
reduces the possibility of optimizations since the
variable may be used after the for statement.
It also makes the job of detecting simple loops
much harder since the declared variable must be tracked
until the end of the enclosing scope. This in turn makes
it less likely that a machine looping instruction will
be generated by the compiler.

The other problem is that it does not fit with the data
hiding philosophy of C++.  The for statement:

	for (statement-1 expression-1 ; expression-2)
		statement-2

should be redefined to be the equivalent of the following
COMPOUND statement:

	{	/* <-- note the enclosing scope */
		statement-1
		while (expression-1) {
			statement-2
			expression-2;
		}
	}

This would let programmers localize the extent of the declared
variable to the FOR statement.  Bjarne could you please fix this.


Cycles for nothing,		|   Ron Irvine, HCR
Mips for free.			

ark@alice.UUCP (Andrew Koenig) (08/22/89)

In article <1807@hcr.UUCP>, ron@hcr.UUCP (Ron Irvine) writes:

> This would let programmers localize the extent of the declared
> variable to the FOR statement.  Bjarne could you please fix this.

Sorry, it's too late.

While working on 2.0 we seriously considered fixing it --
until we discovered how much existing code it would break.
-- 
				--Andrew Koenig
				  ark@europa.att.com

cline@sun.soe.clarkson.edu (Marshall Cline) (08/23/89)

In article <1807@hcr.UUCP> ron@hcr.UUCP (Ron Irvine) writes:
>The expansion of the FOR statement in C++ is great.
>Being able to say "for(int i=0; i<100; ++i) ... " is
>just what I want when I am coding a loop.  However, I
>could not believe that C++ has defined the scope of the
>declared name (i in this case) to be "to the end of the
>block enclosing the for-statement" (pg. 294, of The C++
>programming language).

It's not as pretty, but an extra pair of braces would be a patch.  Ex:
	{for (int i = 0; i < 100; ++i) {
		loop statements;
	}}

>...
>The other problem is that it does not fit with the data
>hiding philosophy of C++.  The for statement:
>	for (statement-1 expression-1 ; expression-2)
>		statement-2

(I'm sure you realize that "statement-1" is restricted to be an "expression"
statement -- I assume the apparently missing ";" is due to the fact that the
"statement" contains it)

>should be redefined to be the equivalent of the following
>COMPOUND statement:
>	{	/* <-- note the enclosing scope */
>		statement-1
>		while (expression-1) {
>			statement-2
>			expression-2;
>		}
>	}

Not quite.  A minor point perhaps, but worth mentioning:
If "statement-2" contains a "continue", the "expression-2" is
still evaluated in the "for", but not in your "equivalent while".

Simple code translators from "for" into "while" are dangerous if
they fail to check for "continue"s.  The only way to deal with them
appears to be to translate them into a "goto" to a label just before
the "expression-2".

Furthermore your extra pair of "{...}" can cause some additional
problems with automated code translations.  For example:
	if (bool1)
		if (bool2)
			for (expr1; expr2; expr3) simple_statement;
		else
			some_other_statement;

Your extra pair of "{...}" will cause the "else some_other_statement;" to
mate with "if(bool1)" rather than with "if(bool2)" -- very bad news.


Not a flame.  I liked Ron's basic idea (although I'm one of the guys whose
code the change would deep-6 since I occasionally use a "break" and then
check the value of the loop var after I exit the loop).

Marshall
--
	__________________________________________________________________
	Marshall P. Cline	Internet: cline@sun.soe.clarkson.edu
	ECE Department		Usenet:   uunet!sun.soe.clarkson.edu!cline
	Clarkson University	Bitnet:   BH0W@CLUTX
	Potsdam, NY  13676	AT&T:     315-268-6591

jgrace@bbn.com (Joe Grace) (08/23/89)

Wait a minute.  Why not *start* fixing it?  Perhaps, by outputting a
warning when code is found which depends on using for() variables
outside the for() body, and claiming that that feature is not guaranteed
to be supported in the next version?  Duplicate declarations of the
same variable within for() loops would be assumed to be *different*
variables.

Or by providing a tool to process files into analogous code but with
the improper variable declarations moved ahead of the for() loop?
[This method wouldn't necessarily work where for() loops are build out
of several macros (at least not without undue complexity to the
tool).]

The first method would allow much code to continue working and yet
make such code "obsolete".  The second method would just fix things up
front without too much trouble to the customer. 

Either fix would make for() loop declarations much more generally
useable in macros and make for() loop declarations analogous to function
header parameter definitions.  Also, the fix would remove the
ambiguity about where the body is in a for() loop without braces (i.e.,
no "new" scope) --- now the new scope would be the for() header
itself. 

= Joe =

Joe Grace
ARPA: jgrace@bbn.com
UUCP: {harvard,husc6,decvax,etc.}!bbn!jgrace
#include <StandardDisclaimer.h>

mpope@augean.OZ (Michael T Pope) (08/23/89)

In article <9803@alice.UUCP> ark@alice.UUCP (Andrew Koenig) writes:
>In article <1807@hcr.UUCP>, ron@hcr.UUCP (Ron Irvine) writes:
>
>> This would let programmers localize the extent of the declared
>> variable to the FOR statement.  Bjarne could you please fix this.
>
>Sorry, it's too late.
>
>While working on 2.0 we seriously considered fixing it --
>until we discovered how much existing code it would break.

Thankyou.  I would have been bitten hard by that.  However, in what
way would one "fix" it?  Surely one does not want to replace the
simplicity of---

  for (<foo>;<bar>;<baz>) <rubbish>  

---being equivalent to---

  <foo>;
  for (;<bar>;<baz>) <rubbish>

---with some new special case behaviour?  

Is there currently anywhere in the language where scope is
defined by anything other than {}s and explicit declaration keywords?
(Well... ignoring file boundaries and function declarations:-)
If not, now is a bad time to start.

Admittedly the for(<decl>...) syntax could be criticized as
potentially misleading, but since the scope of those declarations can
be restricted trivially by wrapping the whole |for| in an extra pair
of {}s the idea looks like mere syntactic sugar to me.

Please dont break |for|.  If restricted scope loop variables
are really desirable, better to invent a new keyword/syntax.

Cheers,
Mike Pope

bright@Data-IO.COM (Walter Bright) (08/24/89)

In article <1807@hcr.UUCP> ron@hcrvx1.UUCP (Ron Irvine) writes:
<Being able to say "for(int i=0; i<100; ++i) ... " is
<just what I want when I am coding a loop.  However, I
<could not believe that C++ has defined the scope of the
<declared name (i in this case) to be "to the end of the
<block enclosing the for-statement"
<One problem with the current definition is that it
<reduces the possibility of optimizations since the
<variable may be used after the for statement.
<It also makes the job of detecting simple loops
<much harder since the declared variable must be tracked
<until the end of the enclosing scope.

There are well-known algorithms for detecting simple (and complex!) loops.
The algorithms work, even if you code your loops as a rat's nest of goto's.
The loop control variable(s) can be detected by analysis rather than looking
at the various parts of the 'for'.
A technique called 'live variable' analysis can be used to determine the
actual scope of a variable, regardless of which block it's declared in,
and whether a loop variable is used after exit from the loop or not.

I've implemented all this in an optimizer I wrote (for Zortech). The
algorithms work, I got them from Aho, Ullman, and Hennesy.

Declaring the loop variable in the for statement or elsewhere has *no effect*
on the ability of the optimizer to optimize the loop. (With the exception
that you really don't want the loop control variable to be global, because
of aliasing problems.) It's just a style issue for the programmer,
sort of like is "if (!i)" better than "if (i==0)".

Of course, there are some weak optimizers out there where the programmers
who implemented them read the wrong books!

<Bjarne could you please fix this.

No need to. I recommend that you read "Compilers, Principles, Techniques, and
Tools" by Aho, Sethi and Ullman. It's available in good university bookstores,
and even some chain bookstores.

ark@alice.UUCP (Andrew Koenig) (08/24/89)

In article <573@augean.OZ>, mpope@augean.OZ (Michael T Pope) writes:

> Thankyou.  I would have been bitten hard by that.  However, in what
> way would one "fix" it?  Surely one does not want to replace the
> simplicity of---

>   for (<foo>;<bar>;<baz>) <rubbish>  

> ---being equivalent to---

>   <foo>;
>   for (;<bar>;<baz>) <rubbish>

> ---with some new special case behaviour?  

No, what we would have done is make

	for (<foo>;<bar>;<baz>) <rubbish>  

equivalent to

	{
		<foo>;
		for (;<bar>;<baz>) <rubbish>
	}
-- 
				--Andrew Koenig
				  ark@europa.att.com