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

Reply via email to