extends keyword instead of <superclass ... >

Allen Wirfs-Brock allen at wirfs-brock.com
Mon Mar 28 12:29:15 PDT 2011


On Mar 27, 2011, at 10:31 PM, Brendan Eich wrote:
> 
> That strawman is essentially functional record update for setting __proto__ AKA [[Prototype]], although it reads backwards compared to FRU in ML-family languages. Those languages put the update on the right, often linked using 'with' (hah!).

It can be viewed that way, although I doubt that the vast majority of current JS programmers would recognize it as such...but that could change over time.

In general, I favor putting what is typically the longer operand second.  Otherwise, the operator and right operand tend to get lost after a long left operand.  In the case of functional record update, it appears that in most usage the update part is longer:
    e with {a=4, b=2}
because the existing object is likely to be referenced via an identifier binding or function call and the update values are more likely to be some sort of longer literal.

The most common case for proto probably is the opposite as the "record" that is being modified is the operand that is more likely to be a long literal form:
   return myProto proto {
      a: 1,
      b:2,
      m1: function () (},
      m2: function () {}
     };

Personally, I think the above makes it more obvious that we are returning an object with an explicitly specified prototype than the following:
  return  {
      a: 1,
      b:2,
      m1: function () (},
      m2: function () {}
     } proto myProto;

However, I acknowledge that in the above the object literal is probably the more important part of the expression and that having it first emphasizes that part.

It may be a toss up, I need to think about whether there are any other constructors in ES with which we should be striving for consistency.  Perhaps, function() {}.bind(e)  is one.

> 
> As you note in the strawman, this enables proto-presetting for a number of built-in classes, not just Object and Array.
> 
> I'm warming up, modulo the backward sense of the connective (also, you need a [no LineTerminator here] to the left of ''proto'' in the productions). Thinking outside the box, indeed.

yep, we want that to be a contextual operator keyword so we need to  be careful about ASI.


> 
> Dmitry's suggestion of #proto or a similar sigil-distinguished name makes me wonder, though: could we have FRU via the spread operator *and* proto presetting without adding a funky [no LineTerminator here] proto infix operator?
> 
>   var original_o = ...;
>   var o = {#proto: p, ...original_o};
> 
> Given this, if you don't have an original_o to specialize (say, a RegExp or other built-in that can't be created via an initialiser), then of course
> 
>   var o = {#proto: p, key: val, ...};

or
  var f= {#proto: p, ...function () {}};
  var r= {#proto: p, .../[a-z]/};
  var a={#proto: p, ...[1,2,3,4]);
???

For the  cases of setting the prototype of a literal function/regexp/array I really prefer forcing the literal into immediate proximity of the prototype.  eg,
   var f = p proto function () {};
or even
   var f = {#proto: p, ...function() {}}
is much better than:
   var f0 = function() {};
   //arbitrary lines of code
   var f = {#proto, ...f0};

If nothing else that latter is going to require significantly more analysis in the front-end to avoid creating two function objects.

Using spread in this way requires generalizing its semantics to copy not just properties but also magic internal properties.

Finally, I really don't want to have to use the
    {#proto: p, ...[1,2,3,4]}
or
   var a0 =[1,2,3];
   var a = {#proto: p, ...a0};
forms for arrays. 

   [#proto: p, 1,2,3]
might be ok, but at the TC39 meetings there were concerns expressed about comma counting.

> 
> should be supported.
> 
> So, infix operators or magic property names?
> 
> For classes, at any rate, it seems to me that On the Outside and Declarative may be at odds, since initialisers are expressions. More below on why.

I'm kinda moving away from thinking that object literal and class declaration forms need to use common syntax.


> 
> 
>>> The strongest case for extending initialiser syntax is that it is "nearly declarative" today. That suggests strongly making the extension fully declarative, i.e., not usable as an expression. And that, all else equal (never is, but:) says to consider class D extends B {...}. My 2 cents.
>> 
>> I don't think "declarative" should not be equated with "not usable as an expression " or introduces a lexical binding.
> 
> It's not clear that classes need to bind their names, or even need names. I believe that some on TC39 want non-generative, nominal run-time types via classes. Others may want generative expressions.
> 
> The consistent #1 request from users that I've heard over the years, most recently in my blog comments, has been for a declarative form of JS's prototypal object-oriented pattern. This conventionally means a new binding. It's generative if you nest it in an outer function, which is not a problem, but usually it is not nested, or else nested only in an outer IIFE (aka the module pattern).


that's the request I'm most interesting in satisfy with a "class" declaration.  In that scenario "class" is close to meaning "constructor function" or just "function". That is why in my proposal
   class Foo {};
is defined to mean almost exactly the same thing as
   function Foo() {};
(but things start to change when you put something between the brackets) and anonymous classes exist as an analog to function expressions.

> 
> 
>> Both function declarations and function expressions are both declarative definitions of functions
> 
> Here is a bit of a nit, but calling both declarative even though one is an expression, not a declaration, sounds like a contradiction, or a redefinition of "declarat{ive,ion}".

I'm using "declarative" more (but not exactly) in this sense: "In computer science, declarative programming is a programming paradigm that expresses the logic of a computation without describing its control flow.[1] Many languages applying this style attempt to minimize or eliminate side effects by describing what the program should accomplish, rather than describing how to go about accomplishing it.[2] This is in contrast with imperative programming, which requires an explicitly provided algorithm." http://en.wikipedia.org/wiki/Declarative_programming 

I would say that:
   ({a,x,b:y,c:z})
is declarative while
   {let obj = new Object;
    obj.a=x;
    obj.b=y;
    obj.c=z;
    obj}
is not. It's imperative.  They are both generative in that they create new objects whose initial state can only be determine at the time they are evaluated.

My usage has nothing to do with binding forms but my terminology seems to be causing confusing with binding  forms in this context.  I don't immediately have a another term at hand  for a non-imperative, non-binding construction expression.  


> 
> More substantive: if we want to enable optimizations and conveniences via syntax for the prototypal pattern, then declarations win, especially if they come with some ahead-of-time semantics, as top-level function declarations evaluated in a compile-and-go scenario do. Thanks to the order of function and then var declaration processing when entering an execution context, such a scenario supports the compiler pre-binding top-level functions.

I'm trying to relate this statement to the original "strongest case" comment above and I'm having a hard time. I probably something more concrete would help. 


> 
> You're right that expressed as well as declared (whether top-level or not) forms could be supported. The question for classes is whether we would ever want an anonymous or named class expression. Just because 'function' can do that does not mean that 'class' must.

A key thing about the proto operator proposal (and different from my earlier meta properties proposals) is that it is trying to specifically  address only the use case of providing an explicit [[Prototype]] for objects created using literal construction forms (object literals, array literals, regexp literals, function expressions).  It  does not currently address classes at all.  If both this proto operator proposal and a class syntax gets adopted we would certainly want to revisit whether there can/should to be an commonality between the two.  It's too early to tell.

Allen
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110328/e4cd58a5/attachment.html>


More information about the es-discuss mailing list