new strawman: syntactic support for private names
Couldn’t you have the same advantages if:
- obj. at foo was syntactic sugar for obj[foo]
- @foo was syntactic sugar for [foo] (method definitions, property definitions, etc.)
foo would be a normal variable and the following two statements would be equivalent: private foo; let foo = new Name();
foo containing a string would also work.
That would be slightly simpler and go together well with your proposed object model reformation [1]: gist.github.com/3505466
Hello.
Two things.
-
If keyword "private" is used for defining the private names (so it is already "used"), why not to use reserved word "public" to define unique names?
-
As for protected scoping issues (though I do not like it, since it makes classes more heavy by looking for @protectedBindings), I would vote for the last proposal, that is, explicitly "import" protected name into class' scope. But the "if there is an inherited, use it, otherwise create new" is tricky, your example shows why: you call super. at validate there. If there wasn't any super @validate, the code breaks.
So for this case, I'd propose not only "protected @foo;" as a means of "use inherited, if none, create your own", but also "protected super @foo;" (or even only "super @foo;", eventually making "super @foo;" silently assume "protected " before itself) as a means of "use inherited, if none, fail".
Yes, I also would like to know why this simpler older model was not good enough.
On Aug 28, 2012, at 4:59 PM, Axel Rauschmayer wrote:
Couldn’t you have the same advantages if:
- obj. at foo was syntactic sugar for obj[foo]
- @foo was syntactic sugar for [foo] (method definitions, property definitions, etc.)
foo would be a normal variable and the following two statements would be equivalent: private foo; let foo = new Name();
There are been various previous runs at defining syntactic support for using unique/private names. They all run into either real or hypothetical usability issues that blocked adoption. One consistent area of concern has been contextual variation in the use of a sigil such as @. For example:
private member; //(no sigil) user just wants to think of "member" as a restricted visibility property key. let obj = {@member: 42}; //they have to remember to use the sigil here because this is a context where identifiers are implicitly quoted let fortytwo = obj[member]; //must not use the sigil here alert(obj. at member); //need to remember to use the sigil here , obj.member would meaning something completely different.
In the above scheme, there is nothing that syntactically identifiers a bound name that is intended to use as a restricted property key. The sigil is a syntactic element of the usage context. Some contexts require one, others do not. A user has to mentally track which identifiers hold property keys and and remember in which contexts a sigil is required or must be avoided.
In my proposal, I attempt to simplify this by making the sigil part of the actual identifier. At the point of declaration, you decide that a certain identifier is going to be used to represent a unique name property key. This decision is reflected in the actual identifier because it must be prefixed with the @. It is also a immutable binding. It's value is guaranteed to be name object that was originally associated with it. All subsequent uses of the identifier must also be prefixed. There is never any confusion about where you are referring to name object based property name or to a string property name. You don't have to remember which context are quoting and which are not.
This seems simple, to me.
foo containing a string would also work.
It's not clear that everybody wants this to work. There were objections to it raised in previous discussions about the computed property names proposal. The language is arguably simpler if @names are restricted to name object values. It isn't clear that the use cases for indirecting through a @name to a string value are important or common enough to justify that additional conceptual complexity. Finally, attempting to initialize at @name to a none name object value will throw an error. That leaves open the possibility of a future extension that allowed them to be initialized to string values.
That would be slightly simpler and go together well with your proposed object model reformation [1]: gist.github.com/3505466
As shown above, I don't think what you are suggest is actually simpler. My proposal works fine with object model reformation,
obj. at name would do a normal [[Put]]//[Get]] using the name object value of @name obj[@name] would do a @elementSet/@elementGet using the name object value of @name.
On Aug 29, 2012, at 4:28 AM, Herby Vojčík wrote:
Yes, I also would like to know why this simpler older model was not good enough.
See my reply to Axel. If you are referring to a simpler older model using the @ sigil, note that we don't actually have one. As far as I'm aware, this is the first complete strawman @ based proposal.
There are been various previous runs at defining syntactic support for using unique/private names. They all run into either real or hypothetical usability issues that blocked adoption. One consistent area of concern has been contextual variation in the use of a sigil such as @. For example:
private member; //(no sigil) user just wants to think of "member" as a restricted visibility property key. let obj = {@member: 42}; //they have to remember to use the sigil here because this is a context where identifiers are implicitly quoted let fortytwo = obj[member]; //must not use the sigil here alert(obj. at member); //need to remember to use the sigil here , obj.member would meaning something completely different.
In the above scheme, there is nothing that syntactically identifiers a bound name that is intended to use as a restricted property key. The sigil is a syntactic element of the usage context. Some contexts require one, others do not. A user has to mentally track which identifiers hold property keys and and remember in which contexts a sigil is required or must be avoided.
In my proposal, I attempt to simplify this by making the sigil part of the actual identifier. At the point of declaration, you decide that a certain identifier is going to be used to represent a unique name property key. This decision is reflected in the actual identifier because it must be prefixed with the @. It is also a immutable binding. It's value is guaranteed to be name object that was originally associated with it. All subsequent uses of the identifier must also be prefixed. There is never any confusion about where you are referring to name object based property name or to a string property name. You don't have to remember which context are quoting and which are not.
This seems simple, to me.
Usability is a good point, people seem to have difficulty with understanding the reification of property names and this would make it simpler.
foo containing a string would also work.
It's not clear that everybody wants this to work. There were objections to it raised in previous discussions about the computed property names proposal. The language is arguably simpler if @names are restricted to name object values. It isn't clear that the use cases for indirecting through a @name to a string value are important or common enough to justify that additional conceptual complexity. Finally, attempting to initialize at @name to a none name object value will throw an error. That leaves open the possibility of a future extension that allowed them to be initialized to string values.
That would be slightly simpler and go together well with your proposed object model reformation [1]: gist.github.com/3505466
As shown above, I don't think what you are suggest is actually simpler. My proposal works fine with object model reformation,
The thought is this: If you use [] to access members of a collection (array, map, etc.) then you’d still have the .@ operator to access properties via computed names. Long-term, .@ would become the recommended way of doing this.
Axel
Axel Rauschmayer wrote:
The thought is this: If you use [] to access members of a collection (array, map, etc.) then you’d still have the .@ operator to access properties via computed names. Long-term, .@ would become the recommended way of doing this.
The last sentence does not follow, even if we make obj. at privateName and obj. at stringName both work.
I'm not (just) saying we should not aspire to such a long-term migration to obj. at name over obj[name]. (I think that we shouldn't want that, btw, but it is not my point.)
I'm saying there is too much history and inertia to believe that just because you can do obj. at anyName, people will move their code to do that, or write all new code some years hence when old browsers have retired that uses only obj. at anyName.
On 29 August 2012 18:39, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
There are been various previous runs at defining syntactic support for using unique/private names. They all run into either real or hypothetical usability issues that blocked adoption. One consistent area of concern has been contextual variation in the use of a sigil such as @. For example:
private member; //(no sigil) user just wants to think of "member" as a restricted visibility property key. let obj = {@member: 42}; //they have to remember to use the sigil here because this is a context where identifiers are implicitly quoted let fortytwo = obj[member]; //must not use the sigil here alert(obj. at member); //need to remember to use the sigil here , obj.member would meaning something completely different.
In the above scheme, there is nothing that syntactically identifiers a bound name that is intended to use as a restricted property key. The sigil is a syntactic element of the usage context. Some contexts require one, others do not. A user has to mentally track which identifiers hold property keys and and remember in which contexts a sigil is required or must be avoided.
In my proposal, I attempt to simplify this by making the sigil part of the actual identifier. At the point of declaration, you decide that a certain identifier is going to be used to represent a unique name property key. This decision is reflected in the actual identifier because it must be prefixed with the @. It is also a immutable binding. It's value is guaranteed to be name object that was originally associated with it. All subsequent uses of the identifier must also be prefixed. There is never any confusion about where you are referring to name object based property name or to a string property name. You don't have to remember which context are quoting and which are not.
This seems simple, to me.
Two observations. First, IIUC, separate namespaces mean that I can not write
let foo = new Name o. at foo = 1
anymore. For first-class names, I would have to fall back to
o[foo] = 1
Wouldn't that reintroduce the very problems we tried to avoid by considering . at foo as a syntax separate from [foo] in the first place, i.e. confusing named property access with indexing collections?
Second, the proposal effectively destroys the first-class nature of @names, because you can only bind them fresh via special declarations, not to the result of some computation. That is, unless you also allow name alias declarations
name @foo = expr
to recover the special syntactic status for a computation's result (i.e., the counterpart to allowing @foo as a free-standing expression). In other words, I think support for name alias declarations has to be an integral part of the proposal, not an optional one.
On Aug 31, 2012, at 12:53 AM, Andreas Rossberg wrote:
On 29 August 2012 18:39, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
There are been various previous runs at defining syntactic support for using unique/private names. They all run into either real or hypothetical usability issues that blocked adoption. One consistent area of concern has been contextual variation in the use of a sigil such as @. For example:
private member; //(no sigil) user just wants to think of "member" as a restricted visibility property key. let obj = {@member: 42}; //they have to remember to use the sigil here because this is a context where identifiers are implicitly quoted let fortytwo = obj[member]; //must not use the sigil here alert(obj. at member); //need to remember to use the sigil here , obj.member would meaning something completely different.
In the above scheme, there is nothing that syntactically identifiers a bound name that is intended to use as a restricted property key. The sigil is a syntactic element of the usage context. Some contexts require one, others do not. A user has to mentally track which identifiers hold property keys and and remember in which contexts a sigil is required or must be avoided.
In my proposal, I attempt to simplify this by making the sigil part of the actual identifier. At the point of declaration, you decide that a certain identifier is going to be used to represent a unique name property key. This decision is reflected in the actual identifier because it must be prefixed with the @. It is also a immutable binding. It's value is guaranteed to be name object that was originally associated with it. All subsequent uses of the identifier must also be prefixed. There is never any confusion about where you are referring to name object based property name or to a string property name. You don't have to remember which context are quoting and which are not.
This seems simple, to me.
Two observations. First, IIUC, separate namespaces mean that I can not write
let foo = new Name o. at foo = 1
anymore. For first-class names, I would have to fall back to
o[foo] = 1
Yes, that is an intentional part of this design. The concept is that @names are similar in usage to immediate values, but ones that have to be explicitly introduced via a declaration.
Wouldn't that reintroduce the very problems we tried to avoid by considering . at foo as a syntax separate from [foo] in the first place, i.e. confusing named property access with indexing collections?
In my proposal . at foo isn't separate syntax. It's a dot, followed by a @name. A simplified version of the grammar as:
MemberExpression : ... MemberExpression [ Expression] MemberExpression . PropertySelector
PropertySelector : IdentifierName AtName
PrimaryExpression : ... AtName
So, there is technically no confusion between property access and indexing collection. Dot and Index access have distinct syntax and semantics. The point of potential conceptual confusion is that AtName used as a PropertySelector and AtName used as a Primary expression evaluate in exactly the same way. This is different from IdentifierName which has different evaluation rules for those two contexts.
We can't treat At-Names in PropertySelector contexts just like IdentifierNames, because in that case an expression like obj. at foo] would means the same thing as obj["@foo"] which is not what we are trying to accomplish. Note, that we would have similar behavior if we allowed string constants to appear immediately after a dot. EG o."foo" o["foo"]
Basically, within the scope of a name/private declaration the best way to think about an AtName is as an immediate representation of its value rather than a variable reference.
I agree this is anomalous, relative to the handling of IdentifierNames but there has to be a anomaly somewhere if we are gong to allow dot property access using unique/private names. In practice, I see little reason for anybody every wanting to say o[@foo] rather than o. at foo. So, I expect people will seldom encounter this anomaly.
Second, the proposal effectively destroys the first-class nature of @names, because you can only bind them fresh via special declarations, not to the result of some computation. That is, unless you also allow name alias declarations
name @foo = expr
to recover the special syntactic status for a computation's result (i.e., the counterpart to allowing @foo as a free-standing expression). In other words, I think support for name alias declarations has to be an integral part of the proposal, not an optional one.
A agree that the initializer in name declaration is very useful and I wouldn't want to be adopted this proposal without it.
On 31 August 2012 19:39, Allen Wirfs-Brock <allen at wirfs-brock.com> wrote:
On Aug 31, 2012, at 12:53 AM, Andreas Rossberg wrote:
Two observations. First, IIUC, separate namespaces mean that I can not write
let foo = new Name o. at foo = 1
anymore. For first-class names, I would have to fall back to
o[foo] = 1
Yes, that is an intentional part of this design. The concept is that @names are similar in usage to immediate values, but ones that have to be explicitly introduced via a declaration.
Wouldn't that reintroduce the very problems we tried to avoid by considering . at foo as a syntax separate from [foo] in the first place, i.e. confusing named property access with indexing collections?
In my proposal . at foo isn't separate syntax. It's a dot, followed by a @name. A simplified version of the grammar as:
MemberExpression : ... MemberExpression [ Expression] MemberExpression . PropertySelector
PropertySelector : IdentifierName AtName
PrimaryExpression : ... AtName
So, there is technically no confusion between property access and indexing collection. Dot and Index access have distinct syntax and semantics. The point of potential conceptual confusion is that AtName used as a PropertySelector and AtName used as a Primary expression evaluate in exactly the same way. This is different from IdentifierName which has different evaluation rules for those two contexts.
We can't treat At-Names in PropertySelector contexts just like IdentifierNames, because in that case an expression like obj. at foo] would means the same thing as obj["@foo"] which is not what we are trying to accomplish. Note, that we would have similar behavior if we allowed string constants to appear immediately after a dot. EG o."foo" o["foo"]
Basically, within the scope of a name/private declaration the best way to think about an AtName is as an immediate representation of its value rather than a variable reference.
I agree this is anomalous, relative to the handling of IdentifierNames but there has to be a anomaly somewhere if we are gong to allow dot property access using unique/private names. In practice, I see little reason for anybody every wanting to say o[@foo] rather than o. at foo. So, I expect people will seldom encounter this anomaly.
Ah, I actually meant something else. You had a proposal to allow indexing via [] to be treated differently from dot projection, and allow the user to redefine it for implementing new collection types. That implies that in the future, it generally is no longer the appropriate operation to use [] to set actual attribute properties (as you usually want to do with private names).
However, with your proposal, it seems necessary to use [] when I want to set a property with a name that is not statically "known" (i.e., perhaps the result of a computation).
For example:
let foo = getMyUniquePropertyName() userCollection[foo] = myUniquePropertyValue
may not have the right meaning, and it is different from what
name @foo = getMyUniquePropertyName() userCollection. at foo = myUniquePropertyValue
would mean. But the latter probably was the intention.
In other words, if you intend to separate access to collection elements from access to object properties in future ES (which I think is a good idea), then we shouldn't rely on using [] to use private properties. But that is the case in the strawman.
The strawman is at strawman:syntactic_support_for_private_names