using Private name objects for declarative property definition.

Allen Wirfs-Brock allen at wirfs-brock.com
Fri Jul 8 16:21:35 PDT 2011


On Jul 8, 2011, at 3:24 PM, Brendan Eich wrote:

> On Jul 8, 2011, at 2:43 PM, Andreas Rossberg wrote:
> 
>>>  Point = {
>>>      //private members
>>>      [__x]: 0,
>>>      [ __y]: 0,
>>>      [__validate](x,y) { return typeof x == 'number' && typeof y =
>>> 'number'},
>>>      //public members
>>>      new(x,y) {
>>>           if (!this[__validate](x,y)) throw "invalid";
>>>           return this <| {
>>>                   [__x]: x,
>>>                   [__y]: y
>>>                  }
>>>       };
>>>      add(anotherPoint) {
>>>            return this.new(this[__x]+another[__x], this[__y]+another[__y])
>>>      }
>>> }
>> 
>> I like this notation most, because it can be generalised in a
>> consistent manner beyond the special case of private names: there is
>> no reason that the bit in brackets is just an identifier, we could
>> allow arbitrary expressions.
> 
> Then the shape of the object is not static. Perhaps this is worth the costs to implementations and other "analyzers" (static program analysis, human readers). We should discuss a bit more first, as I just wrote in reply to Allen.

This is one of the reason I think I slightly prefer the @ approach.  @ can be defined similarly to . in that it must be followed by an identifier and that the identifier must evaluate to a private name object.  The latter in the general case would have to be a runtime check but in many common cases could be statically verified.  Even this doesn't guarantee that we statically know the shape.  Consider:

function f(a,b)  {
    return {
       @a: 1,
       @b: 2
        }
};

const x=Name.create();
const y=Name.create();
let obj1 = f(x,y);
let obj2 = f(y,x);
let obj3 = f(x,x);
let obj4 = f(y,y);

> 
> 
>> So the notation would be the proper dual
>> to bracket access notation. From a symmetry and expressiveness
>> perspective, this is very appealing.
> 
> It does help avoid eval abusage, on the upside.

If you mean something like:
     let propName  = computeSomePropertyName();
     let  obj = eval("({"+propName+":  null})");

I'd say whoever does that doesn't know the language well enough as their are already good alternatives such as:
  let obj = {};
  obj[propName] = null;

or 
  let obj = new Object;
  Object.defineProperty(obj, propName,{value:null, writable: true, enumerable: true, configurable: true});

I know that people do stupid and unnecessary eval tricks today but I doubt that adding yet another non-eval way to accomplish the same thing is going to stop that.  The basic problem they have is not knowing the language and make the language bigger isn't likely to make things any better for them.

> 
> Proceeding bottom-up, with orthogonal gap-filling primitives that compose well, is our preferred way for Harmony. Private name objects without new syntax, requiring bracket-indexing, won in part by filling a gap without jumping to premature syntax with novel binding semantics (see below).
> 
> Here, with obj = { [expr]: value } as the way to compute a property name in an object initialiser (I must not write "object literal" any longer), we are proceeding up another small and separate hill. But, is this the right design for object initialisers (which the normative grammar does call "ObjectLiterals")?
> 

Another concern is that it creates another look-ahead issue for the unify blocks and object initializers proposal.


> 
>> Notation-wise, I think people would get used to using brackets. I see
>> no good reason to introduce yet another projection syntax, like @.
> 
> Agreed that unless we use @ well for both property names in initialisers and private property access, and in particular if we stick with bracketing for access, then square brackets win for property naming too -- but there's still the loss-of-static-shape issue.

There is also an argument to me made that [ ] and @ represent two different use cases: computed property access and private property access and for that reason there should be a syntactic distinction between them.

> 
> 
>> Whether additional sugar is worthwhile -- e.g. private declarations --
>> remains to be explored. (To be honest, I haven't quite understood yet
>> in what sense such sugar would really be more "declarative". Sure, it
>> is convenient and perhaps more readable. But being declarative is a
>> semantic property, and cannot be achieved by simple syntax tweaks.)
> 
> Good point!
> 
> The original name declaration via "private x" that Dave championed was definitely semantic: it created a new static lookup hierarchy, lexical but for names after . in expressions and before : in property assignments in object literals. This was, as Allen noted, controversial and enough respected folks on es-discuss (I recall Andrew Dupont in particular) and in TC39 reacted negatively that we separated and deferred it. I do not know how to revive it productively.

Actually, I think you can blame be rather than Dave for the dual lookup hierarchy.  Dave (and Sam's) original proposal did have special semantics for private name declarations bug only had a single lookup hierarchy.

Allen


More information about the es-discuss mailing list