On Aug 9, 2012, at 8:48 PM, Brendan Eich wrote:

> Luke Hoban wrote:
>> According to the current draft spec text 'let'/'const' are allowed in the 
>> statement list of a switch case, but contribute to the block scope of the 
>> outer block.  This can lead to some confusing situations:
>> 
>> function(x) {
>>    do {
>>         switch(x) {
>>             case 0:
>>                 return x;
>>             case 1:
>>                 let x = 'let';
>>         }
>>     } while (foo());
>> }
>> 
>> The 'x' in 'case 0' here will bind to the later 'let x',
> 
> That's right, let hoists to braced body or block top -- explicit is better 
> than implicit.
> 
> I did this in JS1.7 and we've had years of experience with it, in 
> SpiderMonkey and Rhino. Alternative of implicit per-"case" scope does not 
> work due to C-like fall-through inherited via Java. Programmers do write let 
> in case- and default-labeled statement lists in switches in Mozilla-specific 
> code and I've never heard of a usability problem.
> 
> We could be restrictive (more below), but you have to make a usability or 
> implementation hardship case. I don't think you have.

A more illustrative example for Luke's concerns would be:

function(x) {
   do {
        switch(x) {
            case 0:
                return x;    //always a runtime error
            case 1:
                let x;
                x = 'let';     //never a runtime error
            case 2:
                return x;    //sometimes a runtime error
        }
    } while (foo());
}

The classifications (always, never, sometimes)  of references can be determined 
by a fairly straightforward static analysis. You only need to do a  runtime TDZ 
check on the sometimes case. You can issue compile-time warnings on the always 
and sometimes cases.

>From a usability case we have to consider which is more likely something like 
>the above or something like:

     switch (x) {
       case 0:
           let a = ...;
           // lots of lines of code using a
           break;
       case 1:
            let b = ...;
            // lots of lines of code using b
            break;
        case 2:
            ...
    }
   
My guess was that the disjoint case would be more common and more annoying if 
it was disallowed.  I considered spec'ing each case alternative as a block but 
I concluded it would be unwise to introduce a block scope that was not 
associated with {  }'s.

Basically, the switch body is a block and all the static semantic rules for 
blocks apply to it as do the same dynamic initialize-before-reference TDZ 
rules. This seems straightforward enough to explain to users. The only oddity 
is that it has multiple entry points which means some TDZ violations can't be 
be statically predicted, but that is an optimization issue rather than one of 
user understanding.

Allen
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to