Proposal: opt-out local scoping

Dave Herman dherman at ccs.neu.edu
Thu Aug 28 04:52:19 PDT 2008


I agree with you 100% that JavaScript /almost/ gets lexical scope right 
and that we should try to eliminate that "almost" as much as we can. I 
don't, however, believe that the right solution is Python's implicit 
binding semantics.

> where everything assigned in ... results in a variable local to that
> block. Note that this only affects _assignment_. You can still read from
> a variable from a surrounding scope.

I think you're still going to have the same subtleties as hoisting with 
this proposal, since all the variables assigned to in the block will be 
in scope for the whole block; so they'll be `undefined' before being 
assigned to and there will still be the same closure hazards where you 
might think the variable was in scope in a nested block but in fact it 
goes out to the nearest enclosing var { ... } block.

> var {
>     ...
>     nonlocal x [ = y];
>     ...
> }

For my tastes, this puts too much of a tax on referring to outer variables.

> function list(iterable) {
>     var {
>         if (iterable is Array) {
>             lst = iterable;
>         } else {
>             list = [];

I think you mean `lst = []' here?

>             for (x in iterable) {
>                 lst.push(x);
>             }
>         }
>     }
>     return lst;
> }

These are the kinds of bugs that I think this semantics would result in: 
when assignment implicitly binds variables, fat-fingering an assigned 
variable name silently works and then causes unpredictable behavior 
later. Whereas with traditional lexical scope, when you declare your 
variables up front, both assignments and references are checked against 
the variables in scope, and you get an immediate error -- even 
statically detectable.

I don't believe that

     var {
         ...
         a = f()
         ...
         b = g()
         ...
         c = h()
         ...
     }

is that much less of a hardship than

     {
         ...
         var a = f()
         ...
         var b = g()
         ...
         var c = h()
         ...
     }

and I believe the benefits of a clearer semantics -- and clearer and 
earlier errors on assignment to free variables -- are worth it. But I 
agree that we need to do something to correct the semantics of looking 
up free variables dynamically.

> And finally, it would be nice to have a pragma that can do this for us
> (again, I don't recall the argument against them). Something like:
> 
>     use scope var;
>     use scope let;
>     use scope nonlocal; // default for backwards compatibility

Lexical scope is in the air.  :)  Please take a look at the lexical 
scope proposal on the wiki and offer any comments or suggestions:

     http://wiki.ecmascript.org/doku.php?id=strawman:lexical_scope

Essentially, the above is a less radical proposal that simply uses the 
lexical scope that's already there in JavaScript, but as you suggest 
enforces it with a pragma. The result is a language where free 
variables, both in assignments and references, are a statically 
detectable error, but with otherwise essentially the same semantics that 
JavaScript already has.

Dave


More information about the Es-discuss mailing list