for-loops and declaration-like init expressions

# Andreas Rossberg (11 years ago)

C-style for-loops allow declarations as init statements, but only some of them. Yet, the others (function and class) are actually syntactically legal in that position as well, because they are simply parsed as expressions. Consider:

  let x = 0
  for (let x = 1; ;) x  // 1
  for (const x = 1; ;) x  // 1
  for (function x(){}; ;) x  // 0
  for (class x(){}; ;) x  // 0

I think these latter two examples violate the principle of least surprise. I wonder if it wouldn't be cleaner to rule them out, by imposing the same lookahead restrictions on for-loop init expressions as there are for expression statements.

The one caveat is that for function, that would actually be a breaking change, but is it likely to be a real world one?

What do you think?

# Mark S. Miller (11 years ago)

Why not accept these as for-loop initializations, so that x actually has that function and that class as its initial value in the first iteration of the loop? To me, that's the least surprise. Since this is a position in which some declarations are accepted, anything there that looks like a declaration should be a declaration.

However, I agree that banning these is much less surprising than allowing them as expressions rather than declarations.

# John Lenz (11 years ago)

Would this still be legal, in this scheme?

  for ((function x(){}); ;) x  // 0
  for ((class x(){}); ;) x  // 0
# Will Ray (11 years ago)

Mark, could you explain how the condition and iteration statements in the for loop interact with such an initialization? I agree that banning these seems like the clearer way to go.

# Mark S. Miller (11 years ago)

Consider the function and class declarations in these positions to be equivalent to:

for (let x = function(){}; ...

and

for (let x = class(){}; ...

respectively.

# Mark S. Miller (11 years ago)

for those it is unsurprising that they would be allowed, and that they would be taken as expressions rather than declarations.

# Andreas Rossberg (11 years ago)

On 5 June 2014 17:17, Mark S. Miller <erights at google.com> wrote:

Why not accept these as for-loop initializations, so that x actually has that function and that class as its initial value in the first iteration of the loop? To me, that's the least surprise. Since this is a position in which some declarations are accepted, anything there that looks like a declaration should be a declaration.

Yes, that would be an obvious extension. I did not propose it because it's a less benign change (in the spec) and these cases don't seem particularly useful in practice. That said, I'd be happy with making that change as well, on the grounds that it is more regular.

# Allen Wirfs-Brock (11 years ago)

Over and beyond the breaking change WRT function, I really don’t see the value in such a restriction. There are many pointless or nonsensial things that can be written as expressions. In general, we don’t complicate the language to make such things illegal.

# Mark S. Miller (11 years ago)

Having this be legal as an expression makes the language more complex from the programmer's perspective than either

  • prohibiting this, by allowing only expression-statements as expressions here, or
  • accepting any declaration in this position.

I would be surprised if the status quo were simpler than both of these alternatives from a spec perspective either. Why would this be so?

# Andreas Rossberg (11 years ago)

On 5 June 2014 18:50, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:

Over and beyond the breaking change WRT function, I really don’t see the value in such a restriction. There are many pointless or nonsensial things that can be written as expressions. In general, we don’t complicate the language to make such things illegal.

The point is not so much that it is pointless or nonsensical, but that it has surprising and arguably inconsistent meaning.

# Brendan Eich (11 years ago)

Allen Wirfs-Brock wrote:

Over and beyond the breaking change WRT function,

I bet a tasty donut that we cannot make this breaking change, so why should we fool around with anything similar for class?

# Claude Pache (11 years ago)

Le 5 juin 2014 à 16:58, Andreas Rossberg <rossberg at google.com> a écrit :

The one caveat is that for function, that would actually be a breaking change, but is it likely to be a real world one?

Here is a plausible example:

for (function(){ /* ... */ }(); ; )

Today, the initialisation of that for-loop is interpreted as an IIFE. If it has to be interpreted as a declaration, that becomes a syntax error.

# Kevin Smith (11 years ago)

I bet a tasty donut that we cannot make this breaking change, so why should we fool around with anything similar for class?

I agree. The language would be better and more consistent for the change that Andreas and Mark are suggesting, but it's such an edge case that it's probably not worth the effort.