barrier dimension, default dimension

Andreas Rossberg rossberg at google.com
Sat Dec 29 02:51:28 PST 2012


On 28 December 2012 20:30, David Herman <dherman at mozilla.com> wrote:
>
> Andreas, can you explain why you dismiss TDZ-RBA-UNDEF as a viable option? The bug that motivates all the arguments you've made is read-before-initialization, not write-before-initialization.

I agree that that would be a less error-prone semantics, but other
arguments still apply. IMO it's inferior to "TDZ-UBI-UNDEF" (the
current draft semantics) for three reasons:

1. Complexity/consistency
2. Readability
3. Future-proofness

Regarding (1), consider how to formulate the rules for "unhoisted"
bindings. Informally, "TDZ-UBI-UNDEF" says:

* Accessing a variable before its declaration has been executed is an
error. Furthermore, "let x" is shorthand for "let x = undefined".

The corresponding text for "TDZ-RBA-UNDEF":

* For immutable bindings, accessing a variable before its declaration
has been executed is an error. For mutable bindings, read-accessing a
variable before an assignment to it has been executed is an error.
Furthermore, "let x = e" is shorthand for "let x; x = e". A
let-declaration without a r.h.s. is a conditional assignment of
"undefined" that is performed if and only if no other assignment to
the declared variable has been performed before.

This is clearly less consistent and more complicated, for two reasons.
First, the definition has to be different for mutable and immutable
bindings (there is no such thing as an "assignment" to an immutable
binding). But even ignoring immutable bindings altogether, the
semantics for mutable ones alone are more complicated because of the
runtime case distinction you need to make for the conditional
initialization.

Regarding (2), let me repeat my mantra: reading is 10x more important
than writing. Now consider reading a piece of code like this:

  {
    // lots of stuff
    let x;
    // more stuff
    print(x);
  }

With the current rule, all you need to read to understand what is
printed for 'x' is the code between its declaration and its use. Any
code before the declaration cannot possibly matter, which arguably is
what one would expect intuitively (and what's the case in every other
comparable language with proper lexical scoping). Not so with the
TDZ-RBA-UNDEF rule, where understanding whether the variable is
assigned, and how, generally requires reading _all_ code in that block
up to its use.

Regarding (3), that has been argued before often enough, so I won't
repeat it here. Just let me note that future-proofness is not about
crossing a bridge early, as you seemed to suggest elsewhere, it's
about making sure that you haven't already burnt that bridge once you
get there.

/Andreas


More information about the es-discuss mailing list