Re: Block scoping and redeclarations

2011-08-26 Thread Andreas Rossberg
On 25 August 2011 18:57, Brendan Eich bren...@mozilla.com wrote:
 On Aug 25, 2011, at 6:17 AM, Andreas Rossberg wrote:

 There is no before and after or both here. Hoisting first, with rule 1 
 enforced; then rule 2 checking. Relative source order of declarations is 
 irrelevant.

 pedanticWell, only when you're implicitly assuming a somewhat
 non-standard meaning of across, as rather across or from.
 Clarifying that amounts to the same thing./pedantic

 Please don't over-formalize my words here, that would be a big mistake!

 Hoisting is a very physical metaphor. Hoist that crate! By across I meant 
 across the let declaration in its source position. Not across the let 
 binding which is also hoisted (so I think I see what you mean by across or 
 from -- do I?).

Well, in that case you would not capture the order-independence
properly. Consider e.g.:

  { { var x; ... let x} }

Neither is the var hoisted across the source position of the let,
nor across its scope. Still it's supposed to be an error.

I'm not being entirely academic here. It's exactly details like this
that crop up when you try to implement (and, presumably, specify)
those rules, and they require some ugliness if you want to resolve
everything in one pass.

/Andreas
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Block scoping and redeclarations

2011-08-25 Thread Andreas Rossberg
On 24 August 2011 18:03, Brendan Eich bren...@mozilla.com wrote:
 On Aug 24, 2011, at 2:03 AM, Andreas Rossberg wrote:
 On 23 August 2011 21:18, Brendan Eich bren...@mozilla.com wrote:
 I think the rules we have discussed are:

 1. Any hoisting of var across let binding the same name (whether explicit, 
 or as in catch blocks and comprehensions, implicit) is an early error.

 2. Redeclaration of a name in the same block scope via let, const, or 
 function-in-block is an error.

 That's it. Shadowing via let, const, and function-in-block is allowed 
 (alpha conversion).

 That's fine, although for (1) you probably meant hoisting of var
 across a scope that contains a let binding the same name (or, if you
 assume that let is hoisted to the beginning of its block already, then
 you have to be very careful about specifying the exact order in which
 all the hoisting happens).

 It doesn't matter whether the hoisting is in the same block, or the var is in 
 a block nested within the let's block (or body) scope.

 And for (2), you have to specify whether
 this applies before or after hoisting. In fact, I think it's both,
 since I assume that we want to make both of these an error:

 { let x; { var x } }
 { { let x; var x} }

 There is no before and after or both here. Hoisting first, with rule 1 
 enforced; then rule 2 checking. Relative source order of declarations is 
 irrelevant.

pedanticWell, only when you're implicitly assuming a somewhat
non-standard meaning of across, as rather across or from.
Clarifying that amounts to the same thing./pedantic

 Also, I wouldn't necessarily have regarded catch variables as
 implicitly let-bound. Seems a bit odd, but I guess it's OK to define
 it that way if it does the right thing.

 That is explicit in ES3-in-reality (ES3 was broken), real engines use block 
 scoped catch variable bindings, and those engines that support 'let' (Rhino 
 and SpiderMonkey at least) use exactly the same block-scoping machinery for 
 catch variables as for let bindings.

 We went over this during ES3.1 and ES4 days, here on-list and in TC39 
 meetings. No problem reiterating, I realize that was long before your time 
 :-).

Sorry for digging up old bones then. :) Not a big deal, I just wasn't
aware that you seem to be equating let-bound with block-scoped.
That's a bit surprising for the uninitiated.

 Does it really harm migration? I can see only two scenarios that would
 end up with an illegal redeclaration:

 1) The original function contained a single var x somewhere, and
 somebody is adding a let x now -- this is no big deal, since it is a
 new variable anyway and can easily be chosen differently. (And in
 general, it has to anyway; perhaps better to have a uniform rule of
 thumb here.)

 This costs, you are special-pleading. Oh, migrators can absorb *my* preferred 
 tax, for the greater good *I* see. That's not how the game is played.

Fair enough. My main point here was that migrators are generally
paying that tax anyway, we are just talking about a tax cut for some
cases.

Anyway, I'll rest my case. I remain somewhat unconvinced that the
extra complexity is nil and worthwhile, but there obviously are more
critical topics. We'll go ahead and implement the rules that you
sketched above.

/Andreas
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Block scoping and redeclarations

2011-08-25 Thread Brendan Eich
On Aug 25, 2011, at 6:17 AM, Andreas Rossberg wrote:

 There is no before and after or both here. Hoisting first, with rule 1 
 enforced; then rule 2 checking. Relative source order of declarations is 
 irrelevant.
 
 pedanticWell, only when you're implicitly assuming a somewhat
 non-standard meaning of across, as rather across or from.
 Clarifying that amounts to the same thing./pedantic

Please don't over-formalize my words here, that would be a big mistake!

Hoisting is a very physical metaphor. Hoist that crate! By across I meant 
across the let declaration in its source position. Not across the let binding 
which is also hoisted (so I think I see what you mean by across or from -- do 
I?).


 Anyway, I'll rest my case. I remain somewhat unconvinced that the
 extra complexity is nil and worthwhile, but there obviously are more
 critical topics. We'll go ahead and implement the rules that you
 sketched above.

Thanks. Given the top-level has to accomodate var and let (for disjoint sets of 
names), it shouldn't be much more code to do the same in functions (rather than 
ban mixing of var and let for all names in functions).

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Block scoping and redeclarations

2011-08-24 Thread Andreas Rossberg
On 23 August 2011 19:14, Allen Wirfs-Brock al...@wirfs-brock.com wrote:

 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

That's OK, we are aware that the spec is not finalized yet. For most
part, the semantics is rather obvious, and we try to avoid putting too
much work into aspects that aren't clear yet (such as the global
scope).

 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.

Hm, I'm not sure I remember that we discussed this particular aspect
in detail in July. Sorry if I missed something.

 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.

Oh, but that description does not cover Dave's exact example, which actually was

{ { let x; { var x } } }

Here, the var is hoisted across the let's scope, but doesn't end up in
the same scope. And we clearly want to rule that out, too. But then,
you also want to properly distinguish this case from, say

{ { { let x } { var x } } }

So, while I see what you tried to say there, the fact that it didn't
quite nail it reinforces my feeling that any actual rule might be more
complicated to specify accurately than worthwhile.

 * 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.

I'm not sure I follow. It's not an additional rule -- the way I view
it it is a rule that replaces a (set of) more complicated rule(s). And
if we don't expect the cases in question to show up often, then
doesn't that seems rather like an argument for the simplification than
against it?

That's not to say that I couldn't live with more fine-grained rules, I
just don't consider them worthwhile. Ultimately, we want to morally
deprecate var for Harmony mode, so introducing too many extra rules
around it seems a bit unjustified, unless there is a very good reason.

Thanks,
/Andreas
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Block scoping and redeclarations

2011-08-24 Thread Andreas Rossberg
On 23 August 2011 21:18, Brendan Eich bren...@mozilla.com wrote:
 I think the rules we have discussed are:

 1. Any hoisting of var across let binding the same name (whether explicit, or 
 as in catch blocks and comprehensions, implicit) is an early error.

 2. Redeclaration of a name in the same block scope via let, const, or 
 function-in-block is an error.

 That's it. Shadowing via let, const, and function-in-block is allowed (alpha 
 conversion).

That's fine, although for (1) you probably meant hoisting of var
across a scope that contains a let binding the same name (or, if you
assume that let is hoisted to the beginning of its block already, then
you have to be very careful about specifying the exact order in which
all the hoisting happens). And for (2), you have to specify whether
this applies before or after hoisting. In fact, I think it's both,
since I assume that we want to make both of these an error:

{ let x; { var x } }
{ { let x; var x} }

Also, I wouldn't necessarily have regarded catch variables as
implicitly let-bound. Seems a bit odd, but I guess it's OK to define
it that way if it does the right thing.

 Consequently, we propose a very simple rule instead:

 * 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.)

 Anywhere in the same function? This seems unnecessarily restrictive. People 
 will migrate large functions into ES6 and start let-converting while 
 maintaining. We have seen this happen over the last five years in which we've 
 supported let, in Firefox front-end and add-on JS.

Does it really harm migration? I can see only two scenarios that would
end up with an illegal redeclaration:

1) The original function contained a single var x somewhere, and
somebody is adding a let x now -- this is no big deal, since it is a
new variable anyway and can easily be chosen differently. (And in
general, it has to anyway; perhaps better to have a uniform rule of
thumb here.)

2) The original code contained several var x, and somebody starts
changing some of them into let incrementally -- attempting this does
change the meaning of the code and is extremely likely to break it in
subtle ways. It's probably preferable to flag it as an error.

 * 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; ...}.

 That is covered by my (1) above, no need for special cases. The catch 
 variable is an implicit let binding.

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

 That's also been a point of recurring TC39 agreement, specifically to 
 future-proof for guards.

OK, I'm glad to hear that. :)

Thanks,
/Andreas
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Language modes (Was: Block scoping and redeclarations)

2011-08-24 Thread Andreas Rossberg
 That's not to say that I couldn't live with more fine-grained rules, I
 just don't consider them worthwhile. Ultimately, we want to morally
 deprecate var for Harmony mode, so introducing too many extra rules
 around it seems a bit unjustified, unless there is a very good reason.

Btw, we had this amusing discussion in July how to name the different
language modes without stepping on people's toes. How about classic,
strict, and modern?

/Andreas
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Language modes (Was: Block scoping and redeclarations)

2011-08-24 Thread Allen Wirfs-Brock

On Aug 24, 2011, at 2:08 AM, Andreas Rossberg wrote:
 
 
 Btw, we had this amusing discussion in July how to name the different
 language modes without stepping on people's toes. How about classic,
 strict, and modern?
 

The modern mode won't seem very modern twenty years from now.

allen

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Block scoping and redeclarations

2011-08-24 Thread Brendan Eich
On Aug 24, 2011, at 2:03 AM, Andreas Rossberg wrote:

 On 23 August 2011 21:18, Brendan Eich bren...@mozilla.com wrote:
 I think the rules we have discussed are:
 
 1. Any hoisting of var across let binding the same name (whether explicit, 
 or as in catch blocks and comprehensions, implicit) is an early error.
 
 2. Redeclaration of a name in the same block scope via let, const, or 
 function-in-block is an error.
 
 That's it. Shadowing via let, const, and function-in-block is allowed (alpha 
 conversion).
 
 That's fine, although for (1) you probably meant hoisting of var
 across a scope that contains a let binding the same name (or, if you
 assume that let is hoisted to the beginning of its block already, then
 you have to be very careful about specifying the exact order in which
 all the hoisting happens).

It doesn't matter whether the hoisting is in the same block, or the var is in a 
block nested within the let's block (or body) scope.


 And for (2), you have to specify whether
 this applies before or after hoisting. In fact, I think it's both,
 since I assume that we want to make both of these an error:
 
 { let x; { var x } }
 { { let x; var x} }

There is no before and after or both here. Hoisting first, with rule 1 
enforced; then rule 2 checking. Relative source order of declarations is 
irrelevant.


 Also, I wouldn't necessarily have regarded catch variables as
 implicitly let-bound. Seems a bit odd, but I guess it's OK to define
 it that way if it does the right thing.

That is explicit in ES3-in-reality (ES3 was broken), real engines use block 
scoped catch variable bindings, and those engines that support 'let' (Rhino and 
SpiderMonkey at least) use exactly the same block-scoping machinery for catch 
variables as for let bindings.

We went over this during ES3.1 and ES4 days, here on-list and in TC39 meetings. 
No problem reiterating, I realize that was long before your time :-).


 Anywhere in the same function? This seems unnecessarily restrictive. People 
 will migrate large functions into ES6 and start let-converting while 
 maintaining. We have seen this happen over the last five years in which 
 we've supported let, in Firefox front-end and add-on JS.
 
 Does it really harm migration? I can see only two scenarios that would
 end up with an illegal redeclaration:
 
 1) The original function contained a single var x somewhere, and
 somebody is adding a let x now -- this is no big deal, since it is a
 new variable anyway and can easily be chosen differently. (And in
 general, it has to anyway; perhaps better to have a uniform rule of
 thumb here.)

This costs, you are special-pleading. Oh, migrators can absorb *my* preferred 
tax, for the greater good *I* see. That's not how the game is played.


 2) The original code contained several var x, and somebody starts
 changing some of them into let incrementally -- attempting this does
 change the meaning of the code and is extremely likely to break it in
 subtle ways. It's probably preferable to flag it as an error.

This is indeed the case. Large functions often use var to redeclare canonical 
short-named variables (loop controls, this is most common with for loops). A 
new maintainer free to use 'let' may switch, and find trouble anyway (say they 
change for (var i ...) to for (let i ...) but i is used after the for loop's 
end). There are no guarantees, but you are adding a speed-bump.

The only upside of the speed-bump is implementor convenience. I do not believe 
there's any pedagogical gain in practice. I know from our JS1.7+ experience 
that real code including large functions does mix var and let (_at all_ as 
you put it -- not for the same name). Implementors have to take one for the 
orders-larger developer team.

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Language modes (Was: Block scoping and redeclarations)

2011-08-24 Thread Mike Shaver
On Wed, Aug 24, 2011 at 11:30 AM, Allen Wirfs-Brock
al...@wirfs-brock.com wrote:
 The modern mode won't seem very modern twenty years from now.
 allen

My understanding is that anything after the Middle Ages is fair game,
and I see strict as the middle age between ES.now and ES.future. :-)

MIke
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Language modes (Was: Block scoping and redeclarations)

2011-08-24 Thread Brendan Eich
On Aug 24, 2011, at 2:08 AM, Andreas Rossberg wrote:

 That's not to say that I couldn't live with more fine-grained rules, I
 just don't consider them worthwhile. Ultimately, we want to morally
 deprecate var for Harmony mode, so introducing too many extra rules
 around it seems a bit unjustified, unless there is a very good reason.
 
 Btw, we had this amusing discussion in July how to name the different
 language modes without stepping on people's toes. How about classic,
 strict, and modern?

I once made the mistake of using _NEW as a name part for an opcode in 
SpiderMonkey. Got old fast.

We want few modes, ideally only RFC4329 version numbers on one line, not a 
lattice. This is why Harmony is based on ES5 strict and we do not want an ES6 
stricter strict (use really strict).

The argument in July, which I was lucky enough to (mostly) miss, seemed spec 
jargon bikeshedding. Extended mode vs. something else.

But note that extended is timeless, and if we avoid refracting modes through 
one another, and keep to a linear regime, the spec does not need to distinguish 
ES6 extended from ES7. The spec version itself does that, and (modulo more 
convenient forms for HTML authors) the 6 in script 
type=application/javascript;version=6 means the same thing.

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Block scoping and redeclarations

2011-08-24 Thread Allen Wirfs-Brock

On Aug 24, 2011, at 2:01 AM, Andreas Rossberg wrote:

 On 23 August 2011 19:14, Allen Wirfs-Brock al...@wirfs-brock.com wrote:
 
 
 Oh, but that description does not cover Dave's exact example, which actually 
 was
 
 { { let x; { var x } } }
 
 Here, the var is hoisted across the let's scope, but doesn't end up in
 the same scope. And we clearly want to rule that out, too. But then,
 you also want to properly distinguish this case from, say

This is essentially the same as the hosting a var out of a catch clause where 
the var and catch parameter have the same name.

I tried to get that defined as an error for ES5 and it didn't fly because of 
backwards compat. concerns. I suspect we would come to the same conclusion this 
time.

But, there is nothing stoping an implementation from issuing a warning for such 
occurrences.  It might even be a good idea. We might be able to even get 
agreement to include in the spec. a non-normative recommendation to that regard 
similarly to what ES5 has regarding function declarations within blocks.


Allen___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Block scoping and redeclarations

2011-08-24 Thread Brendan Eich
On Aug 24, 2011, at 9:43 AM, Allen Wirfs-Brock wrote:

 On Aug 24, 2011, at 2:01 AM, Andreas Rossberg wrote:
 
 On 23 August 2011 19:14, Allen Wirfs-Brock al...@wirfs-brock.com wrote:
 
 
 Oh, but that description does not cover Dave's exact example, which actually 
 was
 
 { { let x; { var x } } }
 
 Here, the var is hoisted across the let's scope, but doesn't end up in
 the same scope. And we clearly want to rule that out, too. But then,
 you also want to properly distinguish this case from, say
 
 This is essentially the same as the hosting a var out of a catch clause where 
 the var and catch parameter have the same name.
 
 I tried to get that defined as an error for ES5 and it didn't fly because of 
 backwards compat. concerns. I suspect we would come to the same conclusion 
 this time.

Wasn't the concern theoretical? We have more time now to shake the trees. If we 
find web content with ... catch (e) {... var e...} then we should think hard 
(my migration tax argument cuts all ways). But I've never seen any such code. 
Indeed try/catch is rare, mostly used to ignore deep-throw exceptions at or 
near a top level (event loop).


 But, there is nothing stoping an implementation from issuing a warning for 
 such occurrences.  It might even be a good idea. We might be able to even get 
 agreement to include in the spec. a non-normative recommendation to that 
 regard similarly to what ES5 has regarding function declarations within 
 blocks.

Warnings are mostly fruitless, in my experience. Mostly meaning not that they 
sometimes work (they may, I just don't know), rather that sometimes they just 
bug the heck out of developers and cause a backlash (this happened with 
SpiderMonkey's strict-option warning against 'with', long before ES5 strict), 
or merely degrade the coin of the console.log realm.

/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Block scoping and redeclarations

2011-08-24 Thread Brendan Eich
On Aug 24, 2011, at 10:28 AM, Brendan Eich wrote:

 On Aug 24, 2011, at 9:43 AM, Allen Wirfs-Brock wrote:
 
 This is essentially the same as the hosting a var out of a catch clause 
 where the var and catch parameter have the same name.
 
 I tried to get that defined as an error for ES5 and it didn't fly because of 
 backwards compat. concerns. I suspect we would come to the same conclusion 
 this time.
 
 Wasn't the concern theoretical?

Allen reminded me that the case he wanted to change for ES3.1 was

  with (obj)
var prop = 42;

which insanely binds prop in the enclosing function or global object, but then 
may or may not set obj.prop and leave the prop variable undefined. Nuts, but 
hoisting is consistent, and I (among others on TC39) did not think ES3.1 should 
make a breaking change here. Not just because this might be in web content 
(it's more likely that ... catch (e) { var e... }), but because we weren't 
supposed to be making breaking changes in ES3.1.

Anyway, Harmony is opt-in, and based on ES5 strict so 'with' is *gone*, so only 
the catch (e) { var e... } conflict remains to make an error. Again I believe 
we can get away with this change. It will be an early error, and the pattern 
(unlike free-floating and repeated var usage in big functions) is exceedingly 
rare -- never seen by me in the wild.

/be

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Block scoping and redeclarations

2011-08-23 Thread Andreas Rossberg
We are currently in the process of implementing block scoping for V8
(http://wiki.ecmascript.org/doku.php?id=harmony:block_scoped_bindings).
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).

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:

* 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.)

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.

* 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; ...}.

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

What do you think?

Thanks,
/Andreas
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Block scoping and redeclarations

2011-08-23 Thread John Lenz
I'm in favor of letting let shadow var, but having a var declaration
within a let's scope be a error. I see this as being the most compatible
when working in global scope (and concatenating files).  I suspect that most
new code will quickly move to using let everwhere.


On Tue, Aug 23, 2011 at 5:31 AM, Andreas Rossberg rossb...@google.comwrote:

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

 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:

 * 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.)

 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.

 * 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; ...}.

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

 What do you think?

 Thanks,
 /Andreas
 ___
 es-discuss mailing list
 es-discuss@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Block scoping and redeclarations

2011-08-23 Thread Allen Wirfs-Brock

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


___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Block scoping and redeclarations

2011-08-23 Thread Brendan Eich
On Aug 23, 2011, at 5:31 AM, Andreas Rossberg wrote:

 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

As var hoists to function scope, the order doesn't matter, so what Allen said: 
1[ab], 2a, 3b all should fail with early error (yeah, SyntaxError -- what else? 
:-P), while 2b, 3a, and 4[ab] all succeed.


 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.

I think the rules we have discussed are:

1. Any hoisting of var across let binding the same name (whether explicit, or 
as in catch blocks and comprehensions, implicit) is an early error.

2. Redeclaration of a name in the same block scope via let, const, or 
function-in-block is an error.

That's it. Shadowing via let, const, and function-in-block is allowed (alpha 
conversion).


 Consequently, we propose a very simple rule instead:
 
 * 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.)

Anywhere in the same function? This seems unnecessarily restrictive. People 
will migrate large functions into ES6 and start let-converting while 
maintaining. We have seen this happen over the last five years in which we've 
supported let, in Firefox front-end and add-on JS.


 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.

You got that right ;-).


 * 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; ...}.

That is covered by my (1) above, no need for special cases. The catch variable 
is an implicit let binding.


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

That's also been a point of recurring TC39 agreement, specifically to 
future-proof for guards.

/be
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss