shortcuts for defining block-local private names, plays nicely with @foo syntax

Herby Vojčík herby at mailbox.sk
Mon Jan 23 03:21:56 PST 2012


Allen Wirfs-Brock wrote:
> The plan of record is that ES6 will support the creation of private
> named properties in object literals using syntax like this:
>
> const foo = name.create();
> let obj = {
> [foo]: 42
> };
>
> However, if @foo is going to be used for private named member accesses
> instead of [foo] then it also makes sense to use @ instead of [ ] in
> object literal property definitions. In that case, we should replace the
> above with:
>
> const foo = name.create();
> let obj = {
> @foo: 42
> };
>
> Note that this doesn't run into any of the scoping or multiple name
> space issues that were raised as objections to the original private name
> proposals liked above. Also it doesn't preclude use of [ ] to access
> private names. You could still say either
> obj[foo] or obj. at foo to access the properties whose key is the value of foo
>
> I plan on proposing at the next TC39 meeting that we support .@ member
> accesses and that we replace the use of [expr ] to define private named
> properties in object literals (
> http://wiki.ecmascript.org/doku.php?id=harmony:object_literals#object_literal_computed_property_keys
> ) with @identifier to define such properties.

+1 for adding @foo:x to literals.
Not needing to remove [expr]:x, though.

> Regardless of whether this proposal flies we could consider supporting:
>
> private foo,bar;
>
> as a short hand for:
>
> //assume already done: import name as "@names";
> const foo=name.create(), bar=name.create();

I will repeat myself here, but I would like the 'private foo, bar' to 
have different semantics; that is to be shorthand for something else.

In this code:

   module {
     export function factory1 (args) {
       return {
         @foo: ...,
         ...,
         f(other) { return Math.max(@foo, other. at foo); }
       };
     }

     export function factory2 (args) {
       return { @bar: ..., leq(other) { return @bar < other. at bar; } }
     }

     ...

     // different piece of code copied from web example
     // using its unrelated @bar
   }

The idea here is, product of factory1 and factory2 must play nicely with 
their siblings. So if this would not work:

     export function factory1 (args) {
       private foo;
       return { ...

nor similar for factory2. I'd say majority of Name uses are of this 
kind: so it be the same name in subsequent invocations of the block.

It can be solved this way:

   module {
     private foo, bar;

     export function factory1 (args) { ... }

     export function factory2 (args) { ... }

but then foo and bar are known to the rest of the module. It was not the 
premise. It now clashes with:

     // different piece of code copied from web example
     // using its unrelated @bar

and even if did not, it is bad idea to "globally" define something just 
for local use of little part of code. So, to do this right, one probably 
needs to:

   module {
     {
       private foo;
       export function factory1 (args) {
         return {
           @foo: ...,
           ...,
           f(other) { return Math.max(@foo, other. at foo); }
         };
       }
     }

     {
       private bar;
       export function factory2 (args) {
         return { @bar: ..., leq(other) { return @bar < other. at bar; } }
       }
     }
     ...

     // different piece of code copied from web example
     // using its unrelated @bar
   }

and that's gross :-/.

So, please, consider the possibility, that

   private foo

will not be shortcut for plain and simply writable:

   const foo = Name.create();

but for more complicated

   lexical_singleton foo = Name.create();

so that previous code could be written:

   module {
     export function factory1 (args) {
       private foo;
       return {
         @foo: ...,
         ...,
         f(other) { return Math.max(@foo, other. at foo); }
       };
     }

     export function factory2 (args) {
       private bar;
       return { @bar: ..., leq(other) { return @bar < other. at bar; } }
     }

     ...

     // different piece of code copied from web example
     // using its unrelated @bar
   }

without need to simulate lexically local variable with runtime wrapping.

> I think this would be a desirable addition, but I don't want it to be a
> make or break issue for the .@ proposal.

Yes.

> There are a couple of decision that still need to make for this proposal:
>
> 1) should .@ member access and @ object literal property definitions
> permit he property key to be any toString-able value and not just
> private name values? The current plan of record does not require a
> private name value in the analogous contexts.
> I'm slightly inclined towards requiring private name values, but would
> be happy either way.

Names only. Saves lot of complication below. Makes intent clear.

> 2) elimination of arbitrary expression as direct keys in object literal
> property definitions:
>
> The current "computed property keys" proposals allows things like:
>
> for (var n=0;n<10;) {
> a.push( {
> ["prop"+n]: n++
> });
> }
>
> Do we really need to support this sort of computed property name
> definition? If so, we could probably allow something such as:

It is powerful. Could help a lot in certain situation. I would vote for 
not putting it away.

> for (var n=0;n<10;) {
> a.push( {
> @("prop"+n): n++
> });
> }
>
> I'm include to not supporting the such arbitrary expressions in such
> property definitions, particularly if 1) above is decided as no. Then

Definitely.

> 3) should @foo as a primary expression be interpreted as this. at foo
>
> I think it should, but note that this means that
>
> ... a couple of examples ...
>
> This might be a source of confusion for some JS programmers.

Only for a while. I am for this. at foo. Helps much more than it sometimes 
confuses.

> Allen

Herby


More information about the es-discuss mailing list