I fully agree with your remarks. Infix flags to the "=" operator causes
issues that are difficult to solve. Let's go for a "evertything prefix",
then.
-----Message d'origine-----
From: Sean Eagan
Sent: Monday, May 23, 2011 8:37 PM
To: François REMY
Cc: es-discuss
Subject: Re: Proposal: Concise instance initialisation
On Sat, May 21, 2011 at 5:11 AM, François REMY
<fremycompany_...@yahoo.fr> wrote:
this.c:= 1 looks like an error. If the intent was to set the "c" property
to
a constant, it should not be a function' parameter. If, as I understood,
you
have set a default value for the c parameter, what if you didn't specify
that value?
Then c would be defaulted to 1.
I think it shows that the current 'readonly' syntax (aka :=)
should be reconsiderated, because it's the only one that's postfix (and
the
only one who need an equality symbol after it, which makes it difficult to
exted its use to other locations, as this exemple puts in light).
PROPOSAL: Prefix readonly flag (or postfix everything)
Yes, I think they should all be prefix. I think the non-writable mark
is currently next to the value since they are both data-property-only
attributes, however, it would be easy to just disallow the
non-writable mark before getters and setters. We would need a
different non-writable mark though since = can already take an
assignment expression as its right operand, thus this wouldn't work:
a
=b.c = d
I think we should switch to these marks:
# for non-configurable since it maps to frozen which # represents for
records, tuples etc.
! for non-writable, the lighter weight compared to # matches the
lighter restriction compared to non-configurable
~ for non-enumerable since ~ maps a set of bits into a subset, and
enumeration maps a set of properties into a subset
Postfix would actually look like |a.b = c#!~| which would require a
"no line terminator here" rule, and I don't think infix would work
a.b #!~= c // nice :)
a.b != c // already taken :(
var a = {get b(){return c;}} // no RHS, where do I put the marks ?
Also, the current infix writable mark does not compose with "Implicit
property initialization expressions" [1] as noted in [2]. Using a
prefix fixes this:
let a = {!b}
The problem I see is that it still *may* be non-extendable to other places
(i.e. traditionnal assignations) because the ! symbol is already used as
the
"NOT" operator.
I don't think that's an issue, these all look backward compatible to me:
!a.b = c
!a[b] = c
~a.b = c
~a.b += c
#a.b = c
#!~ a[b] *= c
Another option would be to use only two symbols (I used õ and ñ here, but
we
could imagine using something different) and using them as flags :
ñ not enumerable
õñ not writable
õõñ not configurable
õññ not writable AND not configurable
I think we are restricted to using type-able ASCII characters for
surface syntax.
Also, I prefer a character mapping to an index mapping because:
Characters can be chosen mnemonically (as I tried to do above), index
order is difficult to remember
Less verbose as seen by your last 3 examples.
More visually distinct.
PROPOSAL: Extension to all assignations (here using õñ flags)
function setParent(a) {
a._hasParent ñññ= true;
a.parent õññ= this;
}
function ReadOnlyPoint(this.x õññ, this.y õññ) {} // will be rare in
true code
function setTag(obj, value) { obj.__tag ñ= value; }
function getTag(obj) { return obj.__tag; }
Another beautiful combination could be ~ and :
function setParent(a) {
a._hasParent ~~~= true;
a.parent :~~= this;
}
function ReadOnlyPoint(this.x :~~, this.y :~~) {} // will be rare in
true code
function setTag(obj, value) { obj.__tag ~= value; }
function getTag(obj) { return obj.__tag; }
Please note that in the case of traditionnal assignations, the ! could be
used because the expression before an assignation symbol should not
contains
a NOT operator anyway. It could just be confusing to see things like
"!#obj.boolProperty=!objToCopy.boolProperty" while "obj.boolProperty õññ=
!objToCopy.boolProperty" seems clearer (to me, at least). At least, it
makes
it clear that it's not a simple assignation but a more complex one.
To summarize, I think prefixing with # ~ and ! as above would work
across the board for all types of property assignment.
Also, if destructuring were then extended to allow the individual
LHS's to be property references rather than just Identifiers,
something like this would work:
var [a, #~this.b, !this.c] = arguments;
Then, if destructuring were integrated with parameter lists as I
suggested in "Parameter lists as arguments destructuring sugar" [3],
the "concise instance initialization" use case could be gotten for
free:
function A (a, #~this.b, !this.c){
foo(a);
}
(Maybe a more global remark:)
I know the current mainstream seems to be "please, less characters to
type",
but I'm sincerely under the impression that the more we go in that
direction
the less clear the syntax becomes and the more possible confusions are
introduced. Maybe should we include in every proposal more than one flavor
(and a least a verbose one) so that the different specials chars don't
overlap between all proposals. At the end, the comitee would decide which
proposals will get a short syntax and which will get a longer one, in
order
to avoid different meaning for a same keyword (or symbol) when it can be
confusing (and to maximise the usage of the short syntax in the most
promising proposals while less used pattern would get longer syntax).
I agree that we should be very careful when adding syntax sugar,
however there are clearly cases where it makes sense, and I think this
could be one of them. Also, I think it should be all or nothing, if
we provide sugar for initializing property descriptor attributes, we
should also provide it for modifying them or adding new properties as
that is likely just as common of a use case.
-----Message d'origine----- From: Sean Eagan
Sent: Saturday, May 21, 2011 10:10 AM
To: es-discuss
Subject: Proposal: Concise instance initialisation
Summary:
Update "Object Literal Extensions" [1] to integrate with constructor
parameters for concise instance initialization.
Details:
function f (a, !~this.b, this.c:= 1) {
g(a);
}
// results in f's [[Construct]] ( but not [[Call]] ) behaving like:
function f (a, b, c = 1) {
Object.defineProperty(this, "b", {configurable: false, enumerable:
false, writable; true, value: b};
Object.defineProperty(this, "c", {configurable: true, enumerable:
true, writable; false, value: c};
g(a);
}
Grammar changes to [1] :
FormalParameter :
FormalParameterPrefixOpt Identifier FormalParameterInitialiserOpt
// possibly integrate with destructuring and/or rest parameters as well
FormalParameterPrefix :
PropertyPrefixOpt thisOpt . // "this" is optional
FormalParameterInitialiser :
:Opt Initialiser
[1]
http://wiki.ecmascript.org/doku.php?id=strawman:basic_object_literal_extensions
Cheers,
Sean Eagan
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
[1]
http://wiki.ecmascript.org/doku.php?id=strawman:object_initialiser_shorthand
[2]
http://wiki.ecmascript.org/doku.php?id=strawman:basic_object_literal_extensions
[3] https://mail.mozilla.org/pipermail/es-discuss/2011-April/013570.html
Cheers,
Sean Eagan
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss