return when desugaring to closures

Waldemar Horwat waldemar at
Mon Oct 13 16:54:26 PDT 2008

Brendan Eich wrote:
> On Oct 13, 2008, at 4:01 PM, Waldemar Horwat wrote:
>> Brendan Eich wrote:
>>> If using an uninitialized let binding is an error, then hoisting is
>>> pointless except to make the statements between start of block and the
>>> let declaration a dead zone for the binding name. This fits the
>>> ancient, weak but not entirely worthless post-hoc rationale for var
>>> hoisting (to avoid confusion among novice or inexperienced programmers
>>> by making many scopes, each implicitly opened by var), but it's not
>>> particularly useful.
>> This was our agreement from the ES4 days.  It's very useful, in that 
>> it allows mutually recursive lambdas.
> For function bindings, yes, of course -- but we were talking about let 
> bindings (I thought). For let (there is no 'let function') bindings, 
> how? Could you give an example?

I am talking about let bindings.  Lars brought up at that meeting.  I did not find the use cases particularly convincing, but the dead zone is compelling.  There are four ways to do this:
A1. Lexical dead zone.  References textually prior to a definition in the same block are an error.
A2. Lexical window.  References textually prior to a definition in the same block go to outer scope.
B1. Temporal dead zone.  References temporally prior to a definition in the same block are an error.
B2. Temporal window.  References temporally prior to a definition in the same block go to outer scope.

Let's take a look at an example:

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

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

B2 is bad because then the x inside g would sometimes refer to "outer" and sometimes to "inner".

A1 and A2 introduce extra complexity but doesn't solve the problem.  You'd need to come up with a value for x to use in the very first call to g().  Furthermore, for A2 whether the window occurred or not would also depend on whether something was a function or not; users would be surprised that x shows through the window inside f but g doesn't.

That leaves B1, which matches the semantic model (we need to avoid referencing variables before we know their types and before we know the values of constants).

>>> What's more, as discussed here and in TC39, repeated let declarations
>>> for the same binding name within the same block should be allowed.
>> You can't do that in ES-Harmony.  There is no way to tell if the two 
>> let declarations have the same type.
> There has to be a way to answer the question "are these two terms the 
> same type" at run-time.

I'm sure there will be, but that's not the issue.  What we need to know is that everyone agrees on the type of the variable.  You might write code assuming that the type is set by a nearby let statement, when in fact it's some other let statement that set it.

>> For orthogonality you'd also need to allow multiple const declarations 
>> within the same scope, and I just don't want to go there.
> I don't agree -- const and let are different keywords, they obviously 
> differ in read-only vs. writable binding. They could differ otherwise.

They shouldn't differ any more than that.  If they do, it would just add gratuitous hair to the language.


More information about the Es-discuss mailing list