Brendan Eich (2013-12-25T18:44:21.000Z)
raul mihaila wrote:
> What I want is both similar to A2 and B2, but it's different in that 
> there is only 1 scope for the inner variable.

There is only one inner scope for the braced block in Waldemar's 
example, in any of {A,B}{1,2}:

let x = "outer";
function g() {return "outer"}

{
   g();
   function f() { ... x ... g ... g() ... }
   f();
   var t = some_runtime_type;
   const x:t = "inner";
   function g() { ... x ... }
   g();
   f();
}

Note that function-in-block declarations hoist to top of block -- I 
should have cited that too, for emphasis, in my last message's closing.

> The inner variable is just a local variable, but it's initialized in 
> the hoisting process with the value from the outer scope.

That's unusual -- why would it take on the out same-named variable's 
value? Note it won't work for 'const', only 'let'. Is there any 
difference for 'let' between your proposal and A2, lexical window? Let's 
see, by simplifying the example to make the inner 'const x' into a 'let x':

let x = "outer";
function g() {return "outer"}

{
   g();
   function f() { ... x ... g ... g() ... }
   f();
   let x = "inner";
   function g() { ... x ... }
   g();
   f();
}

Your proposal sounds equivalent to this:

{
   let x = outer`x`; // quasi syntax for outer x
   g();
   function f() { ... x ... g ... g() ... }
   f();
   x = "inner";
   function g() { ... x ... }
   g();
   f();
}

Notice the call g() in f's body, and the call f() before x = "inner". 
This means that f captures (closes over) the block-local x, but its 
value depens on when f is called. The call of f(); right before end of 
block sees x = "inner". The call from just before x = "inner"; sees 
"outer", as does the reference to x in g of course (that capture is not 
in question).

> Initially I was thinking only about var scoped variables but I think 
> this should work for the let scoped variables as well. We would need a 
> new keyword then. Adds some complexity but at least there's only one 
> scope.

There is only one block scope in any event. I am not sure what you mean 
here.

In any case, we aren't adding another keyword, and your approach does 
not work for 'const' at all. For 'let' or any new keyword, it hoists and 
implicitly initializes, which is too implicit and magical, even for JS.

> I didn't study the details about let scope variables in the current 
> spec but I understand that this should throw:
> {
>     (function () {
>         x; // throws - B1 case
>     })();
>     x; // x = undefined, right? - not A1 case because it doesn't throw
>     let x = 10;
> };

First, you don't show any outer x at all, so this involves no 
inner/outer shadowing/windowing/dead-zoning.

Second, the x; before let x = 10; would throw per current spec. I don't 
know what you mean by "not A1" in the comment, since the current spec 
doesn't implement A1 (lexical dead zone), it implements B1 (temporal 
dead zone).

> Currently in FF there's no error here, x is undefined.

Please don't go by implementations yet. They are in various states with 
respect to the ES6 draft spec. Firefox's 'let' dates back to ES4 
proposals. It will be updated.

> In Chrome there's an error about some extended mode which, from what I 
> understand, doesn't exist anymore.

There should be a temporal dead zone error, if you enable the flag for 
harmony_let.

> Currently I achieve what I want by defining a local variable whose 
> name is prefixed with 'local' and assigning it the value I need. It's 
> bad if I want to do the same in multiple execution levels. My proposal 
> is far more readable because it looks less weird.

It's far less readable, though, because of the implicit magic 
initialization from outer shadowed x. What if there is no outer x? And 
'const' does not work at all. We can't have two values for a given 
'const' binding.

/be
domenic at domenicdenicola.com (2014-01-06T14:09:24.566Z)
raul mihaila wrote:
> What I want is both similar to A2 and B2, but it's different in that 
> there is only 1 scope for the inner variable.

There is only one inner scope for the braced block in Waldemar's 
example, in any of {A,B}{1,2}:

```js
let x = "outer";
function g() {return "outer"}

{
   g();
   function f() { ... x ... g ... g() ... }
   f();
   var t = some_runtime_type;
   const x:t = "inner";
   function g() { ... x ... }
   g();
   f();
}
```

Note that function-in-block declarations hoist to top of block -- I 
should have cited that too, for emphasis, in my last message's closing.

> The inner variable is just a local variable, but it's initialized in 
> the hoisting process with the value from the outer scope.

That's unusual -- why would it take on the out same-named variable's 
value? Note it won't work for 'const', only 'let'. Is there any 
difference for 'let' between your proposal and A2, lexical window? Let's 
see, by simplifying the example to make the inner 'const x' into a 'let x':

```js
let x = "outer";
function g() {return "outer"}

{
   g();
   function f() { ... x ... g ... g() ... }
   f();
   let x = "inner";
   function g() { ... x ... }
   g();
   f();
}
```

Your proposal sounds equivalent to this:

```js
{
   let x = outer`x`; // quasi syntax for outer x
   g();
   function f() { ... x ... g ... g() ... }
   f();
   x = "inner";
   function g() { ... x ... }
   g();
   f();
}
```

Notice the call g() in f's body, and the call f() before x = "inner". 
This means that f captures (closes over) the block-local x, but its 
value depens on when f is called. The call of f(); right before end of 
block sees x = "inner". The call from just before x = "inner"; sees 
"outer", as does the reference to x in g of course (that capture is not 
in question).

> Initially I was thinking only about var scoped variables but I think 
> this should work for the let scoped variables as well. We would need a 
> new keyword then. Adds some complexity but at least there's only one 
> scope.

There is only one block scope in any event. I am not sure what you mean 
here.

In any case, we aren't adding another keyword, and your approach does 
not work for 'const' at all. For 'let' or any new keyword, it hoists and 
implicitly initializes, which is too implicit and magical, even for JS.

> I didn't study the details about let scope variables in the current 
> spec but I understand that this should throw:
>
> ```js
> {
>     (function () {
>         x; // throws - B1 case
>     })();
>     x; // x = undefined, right? - not A1 case because it doesn't throw
>     let x = 10;
> };
> ```

First, you don't show any outer x at all, so this involves no 
inner/outer shadowing/windowing/dead-zoning.

Second, the x; before let x = 10; would throw per current spec. I don't 
know what you mean by "not A1" in the comment, since the current spec 
doesn't implement A1 (lexical dead zone), it implements B1 (temporal 
dead zone).

> Currently in FF there's no error here, x is undefined.

Please don't go by implementations yet. They are in various states with 
respect to the ES6 draft spec. Firefox's 'let' dates back to ES4 
proposals. It will be updated.

> In Chrome there's an error about some extended mode which, from what I 
> understand, doesn't exist anymore.

There should be a temporal dead zone error, if you enable the flag for 
harmony_let.

> Currently I achieve what I want by defining a local variable whose 
> name is prefixed with 'local' and assigning it the value I need. It's 
> bad if I want to do the same in multiple execution levels. My proposal 
> is far more readable because it looks less weird.

It's far less readable, though, because of the implicit magic 
initialization from outer shadowed x. What if there is no outer x? And 
'const' does not work at all. We can't have two values for a given 
'const' binding.