Block scoping and redeclarations

Allen Wirfs-Brock allen at wirfs-brock.com
Tue Aug 23 10:14:45 PDT 2011


On Aug 23, 2011, at 5:31 AM, Andreas Rossberg wrote:

> We are currently in the process of implementing block scoping for V8
> (http://wiki.ecmascript.org/doku.php?id=harmony:block_scoped_bindings).

The wiki page spec. is neither complete nor up to date so I wouldn't depend too much on what it says.

I'm in the process of writing the actual draft specification for block scoped declaration and expect to have it ready for review in advance of the next TC39 meeting.  It's up to you, but it might be more economical to put off your implementation for a couple weeks until that spec. is ready 

> Brendan and Dave suggest that certain combinations of `let' and `var'
> should be an error (more precisely, a syntax error, I assume).
> However, there are various possibilities to interpret this. Assume
> that each line in the following is a function scope:
> 
> { let x; var x }  // 1a
> { var x; let x }  // 1b
> 
> { let x; { var x } }  // 2a
> { var x; { let x } }  // 2b
> 
> { { let x } var x }    // 3a
> { { var x } let x }    // 3b
> 
> { { let x } { var x } }  // 4a
> { { var x } { let x } }  // 4b
> 
> 1a-2a should clearly be errors. Same for 3b arguably, because the var
> is hoisted to the same scope as the let. In 2b, 3a, and 4a/b, a var is
> shadowed by a let, which isn't a problem in principle. OTOH, strictly
> speaking, at least 3a and 4a actually introduce a "var-declaration
> that has already been shadowed by a let-declaration" (Dave's words).

I think the July meeting discussion covers all of these cases and I agree that 1a,1b, 2a,3b are errors and 2b,3a,4a,4b are not.

I don't think Dave's quote applies to 3a and 4a.  The var declaration is always logically hoisted to the top of the function so it is already in place before the let block shadows it.  Another way to look at it is that within any scope contour, the same name can not be used within multiple declarations (except for multiple vars for the same name) that occur or are hoisted into that contour.  The order of the multiple declaration doesn't really matter.

> 
> There are lots of arguments that can be made here, but ultimately, my
> feeling is that any rule that allows some of the examples above, but
> not others is both brittle and confusing, and potentially too
> complicated to memoize correctly for the average programmer.
> Consequently, we propose a very simple rule instead:

I think the rule I stated above is fairly simple.  The only complication relates to var which has to get special treatment regardless.

> 
> * It is a syntax error if a given identifier is declared by both a
> let-declaration and a var-delaration in the same function. (And
> similarly, for const vs. var, or function vs. var -- the latter being
> an incompatible change for the global scope, but it seems like we may
> abolish that anyway.)

I'm not sure that this actually simplifies anything. We still need hoisting rules for let and we still need something like the multiple declaration rules above so just is yet another rule that has to be specified, implemented, and remembered by users.  If we think cases such as 3a and 4a are real bug farms then maybe the additional rule carries its weight.  But I'm not sure that we have all that much of a hazard even without it.  I just don't expect to see much code that looked like 3a or 4a.

> 
> We could go even further with the first point: we could make it a
> syntax error to mix var and let _at all_ in a single function,
> regardless of what identifiers they declare. I would be perfectly fine
> with that, too, but expect that others would disagree.

It would probably impede migration to Harmony mode.

> 
> * In a similar vein, I think we should probably forbid `var' to
> coexist with _any_ other form of binding for the same variable in a
> single function. In particular, for Harmony mode we should rule out
> the infamous "try .. catch(x) { var x = 666; ...}".

Also a potential migration problem.  (If it doesn't actually occur on the web it isn't really an issue.  If it does, then forbidding it impedes migration)


> 
> * Finally, do we allow redeclaring functions with let or const, like
> it used to be the case with var? I propose disallowing it.

I agree, at least within function bodies.  I think their may be different considerations for the global scope.

Allen




More information about the es-discuss mailing list