On Mon, Dec 22, 2008 at 1:35 PM, Yuh-Ruey Chen <[email protected]> wrote:
> TBH, even after substituting more Java-esque keywords like "public" for > "reveal", this just doesn't appeal to my aesthetic sense. The user will > naturally wonder why he should do |reveal (privX)| rather than |return > privX|. I'm not sure what the benefit there is to trying to completely > replace functions with lambdas for class methods. > Rather than agree or disagree with this, I'd like to separate issues. The previous message bound together two separable ideas: 1) The notion of "blocks with revealed values" as a TCP amenable way to introduce lambdas while dodging Waldemar's leakage hazard. 2) Enhanced blocks with exported declarations as a better object literal, adapting ideas from Peter Michaux's <https://mail.mozilla.org/pipermail/es-discuss/2008-November/008185.html>. Here, I'll make a revised proposal involving only #2. It will make no use of lambda or reveal, and desugar only to ES3.1 and non-controversial elements of ES-H (const and let declarations) + a placeholder "let" expression syntax for turning a block into an expression without violating TCP. Again, I focus on abstract syntax and am sloppy with the details of concrete syntax. In the absence of another "reveal" concenpt to harmonize with, I will also go back to use of the familiar "public". Without "lambda", I take no position as to how one concretely turns a block into an expression without violating TCP. I would still like to see a TCP-respecting "lambda" and "let", but I'm trying to separate these issues as much as I can. # a restatement of the (abstracted) status quo <block> ::= "{" <statement>* "}" <statement> ::= | <declaration> | <expr> | <otherStatement> # like if, ... <declaration> ::= "var" <ident> ("=" <expr>)? | "const" <ident> (":" <expr>)? "=" <expr> | "let" <ident> (":" <expr>)? "=" <expr> | "function" <ident> <paramList> <block> # the new stuff <expr> ::= ... | "object" ("implements" <expr>) <objectBody> | "let" "{" <statements>* <expr> "}" # Evaluates to the value of the last <expr> <objectBody> ::= "{" (<statement> | <member>)* "}" <member> ::= "public" <declaration> | "public" <ident> (":" <expr>)? "=" <expr> | "public" <ident> <paramList> <block> The sugared form of the previous class-like example, expressed in this language, becomes const Point = Object,freeze(function(privX, privY) { return object implements Point { let privInstVar = 2; const privInstConst = -2; public toString() { return ('<' + getX() + ',' + getY() + '>'); }; public getX() { return privX; }; public getY() { return privY; }; public let pubInstVar = 4; public pubInstConst = -4; }; }); If we wish, we can still introduce a further "class" syntax which desugars to a frozen function returning an object: <declaration> ::= ... | "class" <ident> <paramList> <objectBody> So we could write the above as class Point(privX, privY) { let privInstVar = 2; ... } Both of these desugar to const Point = Object,freeze(function(privX, privY) { return let { let privInstVar = 2; const privInstConst = -2; const toString = Object.freeze(function() { return ('<' + getX() + ',' + getY() + '>'); }); const getX = Object.freeze(function() { return privX; }); const getY = Object.freeze(function() { return privY; }); let pubInstVar = 4; const pubInstConst = -4; Object.freeze(Object.create(Point.prototype, { toString: {value: toString}, getX: {value: getX}, getY: {value: getY}, pubInstVar: {get: function{return pubInstVar;}, enumerable: true}, pubInstConst: {value: pubInstConst, enumerable: true} })) }; }); My previous message mentioned 4 issues it left unaddressed: a) decent concrete lexical syntax b) how can we name the "self" object being initialized? c) how can we provide an alternative to Object.prototype to inherit from? d) how can we simply express revealing a setter as well? On #a, in the absence of "lambda", I think the above concrete sugared syntax is good, modulo the need to decide on an actual concrete syntax for turning blocks into TCP-respecting expressions. On #b, you just say const self = object .. { .. }; The const read barrier has exactly the correct effect: An object can define functions that refer to itself during initialization, but it cannot actually use itself during initialization. Further, two objects defined in the same enclosing scope can refer to each other without any imperative nonesense to set up the cycle. On #c, I revived the earlier notion of "implements" to show how it can be done in the context of this proposal. #d remains unresolved. I didn't like anything I came up with. -- Cheers, --MarkM
_______________________________________________ Es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

