Proposal: Concise instance initialisation

Sean Eagan seaneagan1 at
Mon May 23 11:37:54 PDT 2011

On Sat, May 21, 2011 at 5:11 AM, François REMY
<fremycompany_pub at> 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:

=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

function A (a, #~this.b, !this.c){

> (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]
> Cheers,
> Sean Eagan
> _______________________________________________
> es-discuss mailing list
> es-discuss at


Sean Eagan

More information about the es-discuss mailing list