Request for feedback on a talk on I'm giving on ES6

Allen Wirfs-Brock allen at wirfs-brock.com
Mon Oct 22 09:42:33 PDT 2012


On Oct 22, 2012, at 5:27 AM, Rick Waldron wrote:

> 
> On Monday, October 22, 2012 at 1:04 AM, Domenic Denicola wrote:
> 
>> Thanks for your help Rick! I've corrected a few, but wasn't sure about some others. Let me know if I'm missing something in the following:
>> 
>> From: Rick Waldron [mailto:waldron.rick at gmail.com]
>> Sent: Sunday, October 21, 2012 17:07
>> 
>>> nit: The comment itself says "// error! used a `let` before declaration.", might be nice to highlight that the error will occur until the let is assigned, ie. I can initialize it, but reads will throw until it's assigned.
>> 
>> If I'm understanding you correctly, you're saying that this should throw?
>> 
>> let x;
>> assert(x === undefined); // error! Use of `x` before it is assigned.
> yes, any read access will throw before assignment. 
>> 
>> I was under the impression the temporal dead zone was about use-before-definition, not use-before-assignment.
> There is no deadzone in the former, it's use-before-assignment 
>  

No, Domenic is correct.  It is "use before initialization".  Let bindings that lack an initializer have an implicit "=undefined" initializer.


>> (For const they are the same, since the "Static Semantics: Early Errors" note on page 125 of the spec gives a Syntax Error if the Initialiser is omitted from the LexicalBinding.) That is:
>> 
>> "A let and const declarations define variables that are scoped to the running execution context’s LexicalEnvironment. The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable’s LexicalBinding is evaluated. A variable defined by a LexicalBinding with an Initialiser is assigned the value of its Initialiser’s AssignmentExpression when the LexicalBinding is evaluated, not when the variable is created. If a LexicalBinding in a let declaration does not have an an Initialiser the variable is assigned the value undefined when the LexicalBinding is evaluated."

A missing initializer in a const declaration is defined as syntax error by the first Early Error rule in section 12.2.1 which is for the production LexicalBinding : BindingIdentifier

The note quoted above is an informative note and not normative language.   What it describes is accurate but is expressed in a more precise, but less centralized manner by the normative algorithms and rules of the specification,

>> 
>> This implies to me that the first line above evaluates the LexicalBinding, assigning the variable the value undefined; since the LexicalBinding is evaluated, the "may not be accessed" clause no longer applies, and no error should occur.
> 
> I'm not sure the full temporal deadzone semantics are even in a draft yet (like lots of things) 

Yes, it's are all there, at least for function level declarations. Of course, there could be errors so read deeply...

 The global scope will be in the next draft.

>> 
>> 
>>> Not sure of the number, but there is a slide titled "Block Scoping" with this:
>> 
>>> if (Math.random() > 0.5) {
>>>   function go() {
>>>     console.log("gone!");
>>>   }
>>>   ...
>>> }
>>> assert(typeof go === "undefined");
>> 
>>> I'm not sure I get what this one is trying to illustrate, because "go" will always be initialized, regardless of the condition
>> 
>> I believe this is not true. The current semantics for block-scoped functions bind them to the block, not to the surrounding function. (That is, a FunctionDeclaration creates an entry into LexicallyDeclaredNames, not into VarDeclaredNames.)
>> Even in ES5, this behavior is unspecified: see the "NOTE" under the "Semantics" heading under section 12 of ES5.1, where it notes that even though Statement does not include FunctionDeclaration, implementations often allow it, with "significant and irreconcilable variations." (So, I don't think "go" will always be initialized in all browsers. For example, in IE10 strict mode the above code is a SyntaxError.) It also says that "Future editions of ECMAScript may define alternative portable means for declaring functions in a Statement context."
>> 
>> And indeed, in ES6 the Declaration grammar production is introduced as a sibling to Statement under Block. It includes LexicalDeclaration and FunctionDeclaration; VariableStatements are left under Statement. And the Block Declaration Instantiation algorithm (10.5.4) includes both LexicalDeclarations and FunctionDeclarations, i.e. FunctionDeclarations are added to the block's Declarative Environment Record instead of to the environment record of the containing function.

Yes, function declarations are block scoped and are not hoisted to the surrounding function.

In the above example, the asset is outside the block that defines go, so the declaration is invisible.  so,  result is going to be just like ES5: either a Reference Error or undefined, depending upon rather it is strict mode or not.

>> 
>>> new Set(...document.body.children);
>> 
>>> is a Syntax Error, use: 
>> 
>>> new Set([ ...document.body.children ]);
>> 
>>> Same for: 
>>> new Set(...array)
>>> Math.max(...array);
>>> Math.max(0, ...array, 5, ...array2);
>>> new Date(...dateFields);
>>> array.push(...array2);
>> 
>> I don't think any of these is a syntax error, since spread works for function calls/constructs too. See http://tc39wiki.calculist.org/es6/spread/ or section 11.2.5 of the draft spec wherein the expanded runtime semantics for ArgumentListEvaluation are given (in particular ArgumentList: ...AssignmentExpression and ArgumentList: ArgumentList, ...AssignmentExpression). However, you are right that the sets should be constructed that way, since the Set constructor accepts an iterable and not varargs. Much appreciated!
> Not according to SpiderMonkey, so someone has a bug.

I just (yesterday) wrote the spec. language for Set and it takes a single optional iterable argument.  I don't see anything on the TC39 wiki to suggest otherwise.  We can't have a single method/function that is overloaded with both a rest parameter and single iterable as the iterable case would look like a single element rest.  Given that we are using iterable at a number of places to initialize collections we should be consistent in that usage.  If we want to provide a factory that likes a rest parameter then it should be Set.from(...values)

Allen

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20121022/a6245a2e/attachment.html>


More information about the es-discuss mailing list