At the Harmony portion of the recent EcmaScript meeting, we took up the classes as sugar discussion. For background, the relevant recent threads on es-discuss are:
"Look ma, no this" thread starting at https://mail.mozilla.org/pipermail/es-discuss/2008-November/008181.html "How much sugar do classes need?" thread starting at https://mail.mozilla.org/pipermail/es-discuss/2008-November/008181.html especially Peter Michaux's https://mail.mozilla.org/pipermail/es-discuss/2008-November/008185.html "Block exprs as better object literals" thread starting at https://mail.mozilla.org/pipermail/es-discuss/2008-December/008521.html continuing in January starting at https://mail.mozilla.org/pipermail/es-discuss/2009-January/008525.html The discussion was a bit frustrating because the committee was largely unaware of the last two of these threads. Although I do recommend reviewing them, I will here restate and refine my last suggestion in a self contained pair of messages. Again, I would like to thank Peter Michaux for the general approach. Since the proposal I'm about to make will be in terms of a desugaring to other elements of ES-Harmony, In this first message I will recap and speculate on the needed elements of ES-Harmony. Since "lambda" is still controversial, I will avoid it. But I will introduce instead the minimal replacement I still need -- a "let" expression which respects Tennent Correspondence. I would hope that this "let" actually desugars to "lambda", but I do not assume this here. If we do adopt "lambda", then all the desugaring I present to functions should instead be to lambdas. We need to refactor the ES5 grammar a bit. ES5 has two statement-level declaration productions, VariableStatement and FunctionDeclaration. In ES5, VariableStatement is included in Statement, whereas FunctionDeclaration is included in SourceElement, which reads SourceElement: // ES5 Statement | FunctionDeclaration The reason is that ES5 prohibits FunctionDeclarations in nested blocks, permitting them only at the top level of Program and FunctionBody. Since ES-Harmony will allow lexically nested FunctionDeclarations as well as "let" and "const" declarations, all with proper block-level lexical scope, let's rename VariableStatement to VariableDeclaration and refactor the grammar as: Declaration: VariableDeclaration | FunctionDeclaration | ConstFunctionDeclaration | LetDeclaration | ConstDeclaration | ClassDeclaration with ClassDeclaration explained in the next message. The important point for now is that ClassDeclaration desugars to, in effect, declare a function. Like a harmonious FunctionDeclaration, the name declared by a ClassDeclaration has proper block-level lexical scope, and the initialization of this name to the function is hoisted to the beginning of the block so no uninitialized state is observable. LetDeclaration: "let" Identifier (":" Expression)_opt "=" Expression ConstDeclaration: "const" Identifier (":" Expression)_opt "=" Expression The optional (":" Expression) is for dynamic type checking, where the expression is evaluated to a guard value in the current lexical scope, and that guard value is somehow used to represent type-like constraints on the values that may be bound to the variable it guards. Statement: // current Statement contents without VariableStatement SourceElement: Statement | Declaration Block: "{" SourceElements_opt "}" MemberExpression: // current MemberExpression contents | LetExpression | ObjectExpression with ObjectExpression explained in the next message. LetExpression: "let" Bindings_opt "{" SourceElements_opt Expression "}" For purposes of this note, we can assume Bindings_opt is absent. Likewise, this note has no need for a LetStatement. The semantics of the LetExpression (due, IIRC, to a suggestion of Dave Herman) is to evaluate the parts between the curlies as a nested block, where the value of the LetExpression is the value of the terminal Expression in its body. The ConstFunctionDeclaration above elaborates on someone's suggestion, I forget who, for a syntax like: ConstFunctionDeclaration: "const" Identifier "(" FormalParameterList_opt ")" "{" FunctionBody "}" This is just like the FunctionDeclaration syntax except for the use of "const" in the position where "function" normally appears. Like a FunctionDeclaration and a ClassDeclaration, a ConstFunctionDeclaration declares a block-scoped hoisted function. For example, const foo(p1, p2) { body; } desugars to const foo = Object.freeze(function foo(p1, p2) { body; }); Object.freeze(foo.prototype); where this pair is hoisted to the top of its enclosing block. It would have been more elegant if we could have desugared directly to a FunctionDeclaration, in order to reuse the latter's hoisting machinery. However, we can't since the variable introduced by FunctionDeclaration is mutable ("let"-like) and there's no way to get the freezing of the function or its prototype to be automagically hoisted as well. Hopefully the introduction of "lambda" will provide a more elegant way to address this need. If neither lambda nor ConstFunctionDeclaration are accepted into ES-Harmony, then consider the latter as only an explanatory device for other desugarings to be presented shortly. -- Cheers, --MarkM _______________________________________________ Es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

