tags:

views:

460

answers:

6

we can do:

 using (Stream s ..)

and:

 for (int i ...)

why can't we as well do something like:

 while ((int i = NextNum()) > 0) {..}

i find it very useful and sensible.

+1  A: 

Because then it's defined in every iteration. A for loop doesn't do that. (So you cant define it again after the first loop. Since it already exists.)

Ólafur Waage
but why? and anyway, be it.. it'll be defined in each iteration.. why not?
Itay
+7  A: 

I'm not a language designer, but I'll give it an educated guess.

The clause inside the while() is executed every single time the loop is executed. (+1 more time at the end.) The statement int i = NextNum() declares a local variable. You can't declare a local variable more than once.

Update

Semantically, it makes sense that this should be possible. In fact, as pointed out in the comments, this is possible in other languages. However, this would not be possible in C# without re-writing some major syntax rules.

Local variables must be declared in a statement. I believe the language to be separated this way because a variable declaration is not really executed. When you see a line of code that creates a variable and assigns it a value, that is actually just a shortcut for two statements. From the ECMA-334 Specification:

The example

void F() {
   int x = 1, y, z = x * 2;
}

corresponds exactly to

void F() {
   int x; x = 1;
   int y;
   int z; z = x * 2;
}

The variable declaration part by itself is not "executed". It just means that there should be some memory allocated on the stack for a certain type of variable.

The while statement is expecting a boolean expression, but an expression cannot be composed of a statement -- without a special casing some new grammar.

The for loop is specially designed to declare a local variable, but you'll note that declaration part is "executed" only once. The using statement was specifically designed to declare local variables (and dispose of them). It is also "executed" only once.

Also consider that a local variable declaration doesn't return a value -- it can't since the it allows you to declare multiple variables. Which value would this statement return?

int x = 1, y, z = x * 2;

The above statement is a local-variable-declaration. It is composed of a type, and three local-variable-declarators. Each one of those can optionally include an "=" token and a local-variable-initializer To allowing a local variable to be declared in this manner would mean that you pull apart the existing grammar a bit since you would need the type specifier, but mandate a single declarator so that it could return a value.

Enabling this behavior may nave negative side effects also, Consider that the while and do/while statements are opposite, but parallel. As a language designer, would you also enable the do statement to declare a local variable? I don't see this as possible. You wouldn't be able to use the variable in the body of the loop because it wouldn't have been initialized yet (as of the first run). Only the while statement would be possible, but then you would destroy the parallelism between while and do statements.

Matt Brunell
I second Matt's assertion - you'd be re-declaring i each time your loop executed.
Zannjaminderson
why can't you define local varible more than once?
Itay
@Itay maybe because you would loose scope of everything else as well?
Dave
@dave i don't understand.. create the varible each iteration.. you don't need it's old value.
Itay
There's no reason why the variable couldn't be created and destroyed for each iteration (like a variable declared in the loop body). Other languages allow exactly this.
Andrew Medico
"The clause inside the while() is executed every single time the loop is executed."Every single time + 1 !!!
Shankar Ramachandran
@Xencor, good point. I added a notation.
Matt Brunell
+8  A: 

Don't know for certain but here is my educated guess.

The for case works because it actually has 3 parts.

  1. The iteration variable
  2. The terminating condition
  3. The increment

These 3 run differing amounts of times. #1 runs only once, #2 runs number of iterations +1 and #3 runs once per iteration. Since #1 runs only once it's a nice and clean place to define a variable.

Now lets examine the while loop. It only has 1 part and it runs every iteration + 1. Since it runs every single time it's not a great place to define a variable which must necessarily be a part of the condition. It raises questions like

  • Should the define happen once or once per iteration? If it's the latter how many people will misunderstand this and mess up the conditional? If it's the former then you have a complete statement of which only part executes once per query
  • How do multiple variable defines behave?

I'm guessing the complexity / ambiguity is one of the reasons why it's not allowed. That and it's probably never been high on the priority list.

JaredPar
This is a good line of thought. Clincher - "never been high on the priority list."
Shankar Ramachandran
My thoughts exactly. The for loop has more structure to it and it makes sense to allow initialization when you're defining the starting point for a given variable. But the while loop is free form and the condition is literally executed at every iteration. I don't know, even it were allowed, I wouldn't think of it as a good coding practice to define the variable in the while loop.
Steve Wortham
+1  A: 

There's no inherent reason why it couldn't be done - the C# designers just chose not to allow it. It works just fine in Perl, for example ("while ((my $i = NextNum()) > 0) { ... }").

Andrew Medico
the question is WHY did they..
Itay
+2  A: 

As opposite to the 'for' loop, 'while' doesn't have a initialization part. The 'for' syntax looks like this:

for ( initializer; conditional expression; loop expression)
{
      statements to be executed
}

and the 'while' looks like this:

while (condition)
{
      statements to be executed
}

The closest thing to your request is:

int i;
while ((i = NextNum()) > 0) { ... }
Fernando
or just for (int i; i > 0; i = NextNum())but i want to know why it can't work with while :P
Itay
A: 

Variable declarations are statements; the while loop expects an expression (an expression can be a statement, but not the other way around). using and for, on the other hand, are special-cased to allow variable declarations.

More importantly, the scope of such a thing would be unclear. Consider:

int x;
// ...
y = (int x = 42) + x;
// what is y?

Or worse:

(int x = 42) + (int x = 42);

Or even:

(int x = 42, y = 24) // what is the value of this expression?

Once you allow declarations be expressions, you have to deal with these things. In particular, the last example becomes a problem because it's hard to disambiguate between expression-declaration-as-a-statement or statement-declaration, so the expression style will have to be general enough to be how we do statement declarations.

This is starting to get to be a bit of a hairy design challenge, and since it's not really a very important feature, it's likely the C# committee decided not to allow declarations be expressions (or they simply never thought of it :).

Finally, you can actually get what you want with just a for loop. For example:

while ((int i = NextNum()) > 0) {..}
// becomes...
for (int i; (i = NextNum()) > 0; ) {..}
// or...
for (int i = NextNum(); i > 0; i = NextNum()) {..}
bdonlan