Classes: suggestions for improvement

classic Classic list List threaded Threaded
39 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Classes: suggestions for improvement

Axel Rauschmayer
I really like the proposal: it is very lightweight syntactic sugar. For example, it is not that radically different from Resig’s Simple Inheritance (whose "look" I like). The "super" keyword for calling overridden methods and chaining super-constructors and the "static" keyword for defining class properties are welcome additions. Especially "super" saves a lot of boilerplate code.

Minor suggestions for improvement:

(1) The syntax for private properties still is a bit clumsy, and @ feels like wasting a nice symbol, how about using private.foo instead of private(this).foo?

(2) "public" feels superfluous in class body and the word "public" does not really denote the opposite of "static".

(3) Is "static const" possible?

This is a bit farther out: There is a use case for having a superclass and 0 or more prototypes at the same time. The former is useful for constructor chaining, the latter could be used to implement poor man’s traits. Then the prototype chain would look like this:

subTypeInstance |> SubType.prototype |> Trait1 |> Trait 2 |> SuperType.prototype


Does anybody know what Brendan meant in this txjs talk with “Classes made it (Yay, I think? Why am I sad?)”? Is he ambivalent about the proposal? Is there anything he doesn’t like?

Axel

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Brendan Eich-3
On Jun 12, 2011, at 2:22 PM, Axel Rauschmayer wrote:

(1) The syntax for private properties still is a bit clumsy, and @ feels like wasting a nice symbol, how about using private.foo instead of private(this).foo?

No, you need private(other).foo or shorter for things like

 class Point {
   constructor(x, y) {
     private x = x;
     private y = y;
   }
   equals(p) { return private(this).x === private(p).x && private(this).y === private(p).y; }
   ...
 }

BTW, @ is hardly "wasted" as shorthand, since the above is way too long and also requires reifying private data as an object, which we do not want (I mean, I believe no one wants).


(2) "public" feels superfluous in class body and the word "public" does not really denote the opposite of "static".

Especially when it's not the opposite anyway: "proto" would be better but it is unnecessary.


(3) Is "static const" possible?

Yes, see 


This is a bit farther out: There is a use case for having a superclass and 0 or more prototypes at the same time. The former is useful for constructor chaining, the latter could be used to implement poor man’s traits.

This proposal is about prototypal inheritance sugar only. Mark split out the traits stuff for good reason, and we wouldn't want to be poor men (or women) if we could have real traits.


Does anybody know what Brendan meant in this txjs talk with “Classes made it (Yay, I think? Why am I sad?)”? Is he ambivalent about the proposal? Is there anything he doesn’t like?

You can just ask me ;-).

Something about classes in JS makes me sad, an emotional effect I can't explain fully. In part I fear the "lint brush" aspect I mentioned in the thread Irakli just followed up: class syntax will grow lots of hair over time. In part I think class is the wrong word, as cowboyd tweeted (see below).

Mainly I think we are still finding class syntax, not just the keyword, a bit hard to fit to the prototypal pattern. The super keyword in limited expression forms is no problem. The extends and prototype "Heritage" clause in the class head is ok.

The constructor flows from the prototype-methods-at-class-element-position design, but starts to rankle, if only because of the name's length. As you can see in my posts today, it seems to go downhill from there. And we're still trying to find a better syntax than the "static" keyword.

/be

(I hope this twitter converation is readable.)

Charles Lowell
 It's a small thing, and I'll get over it, but something about "class" fills me with melancholy.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Brendan Eich-3
On Jun 12, 2011, at 2:38 PM, Brendan Eich wrote:

>> (3) Is "static const" possible?
>
> Yes, see

Oops, accidentally cut "the grammar".

ClassPropertyDefinition :
    static ExportableDefinition
ExportableDefinition :
    Declaration

and Declaration : const Pattern.

/be

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Brendan Eich-3
In reply to this post by Axel Rauschmayer
On Jun 12, 2011, at 2:22 PM, Axel Rauschmayer wrote:

> I really like the proposal: it is very lightweight syntactic sugar. For example, it is not that radically different from Resig’s Simple Inheritance (whose "look" I like).

There is good in the proposal, don't get me wrong. I worked on it at the end, because I believe developers want sugar for the prototypal pattern, they've said so often.


> The "super" keyword for calling overridden methods and chaining super-constructors

Yes, this is good but somewhat separable from class {...}, although we need a context in which "super" makes sense as a special form.


> and the "static" keyword for defining class properties are welcome additions.

Why "static" is the wrong word: there is nothing compile-time about the class properties. Classes are expressible (anonymous, even), as well as declarable in nested (generative) ways.

Using "class" does not work if one wants nested classes, although the default that binds prototype properties for ExportableDefinitions including Declarations seems like exactly the wrong default: how often do you want class Outer { class Nested {} ... } to make Nested a property of Outer.prototype, instead of a class property (Outer.Nested)?

Again, the grammatical retasking of certain Declarations to bind prototype properties (instead of lexical bindings in the class body, or perhaps class properties -- but perhaps not) seems like a mistake.

/be

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Brendan Eich-3
In reply to this post by Brendan Eich-3
On Jun 12, 2011, at 2:38 PM, Brendan Eich wrote:

> Something about classes in JS makes me sad, an emotional effect I can't explain fully. In part I fear the "lint brush" aspect I mentioned in the thread Irakli just followed up: class syntax will grow lots of hair over time. In part I think class is the wrong word, as cowboyd tweeted (see below).
>
> Mainly I think we are still finding class syntax, not just the keyword, a bit hard to fit to the prototypal pattern. The super keyword in limited expression forms is no problem. The extends and prototype "Heritage" clause in the class head is ok.
>
> The constructor flows from the prototype-methods-at-class-element-position design, but starts to rankle, if only because of the name's length. As you can see in my posts today, it seems to go downhill from there. And we're still trying to find a better syntax than the "static" keyword.

Let's say we can make classes mean what we want. Per the agreement to promote them into Harmony with open issues, we are "close enough".

But we still need to nail those open issues. This requires considering alternatives carefully and writing down everything pro and con. It'll be tedious work, without easy answers (at first). I'm game to do it here, although others may fear the Inbox load.

Reflecting on classes in JS, at a high level I feel we are falling into the gravity well of a dying star. It could supernova, in which case we will be burned. Or it could black-hole and we'll get rent by tides before going somewhere else ;-).

Ok, fun metaphor but I'm not totally kidding. The gravity well is created by the mass of "class expectations" from other languages, plus de-facto "prototypal" and other patterns in JS. Heavy.

/be

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Axel Rauschmayer
In reply to this post by Brendan Eich-3
(1) The syntax for private properties still is a bit clumsy, and @ feels like wasting a nice symbol, how about using private.foo instead of private(this).foo?

No, you need private(other).foo or shorter for things like

 class Point {
   constructor(x, y) {
     private x = x;
     private y = y;
   }
   equals(p) { return private(this).x === private(p).x && private(this).y === private(p).y; }
   ...
 }

BTW, @ is hardly "wasted" as shorthand, since the above is way too long and also requires reifying private data as an object, which we do not want (I mean, I believe no one wants).

What confuses me slightly is that it initially looks like private and public properties share the same namespace, but later don’t seem to. Maybe it would be better to make the different namespaces explicit:

 class Point {
   constructor(x, y) {
     private @x = x;
     private @y = y;
   }
   equals(p) { return this.@x === p.@x && this.@y === p.@y; }
   ...
 }

Maybe something like the following would work, too:

private.x = x;
...
return this.private.x === p.private.x;




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Axel Rauschmayer
In reply to this post by Brendan Eich-3
>> and the "static" keyword for defining class properties are welcome additions.
>
> Why "static" is the wrong word: there is nothing compile-time about the class properties. Classes are expressible (anonymous, even), as well as declarable in nested (generative) ways.
>
> Using "class" does not work if one wants nested classes, although the default that binds prototype properties for ExportableDefinitions including Declarations seems like exactly the wrong default: how often do you want class Outer { class Nested {} ... } to make Nested a property of Outer.prototype, instead of a class property (Outer.Nested)?
>
> Again, the grammatical retasking of certain Declarations to bind prototype properties (instead of lexical bindings in the class body, or perhaps class properties -- but perhaps not) seems like a mistake.


Terminology-wise, I have always avoided the word “class” in JavaScript and used the word “type”, instead (with, roughly, constructors implementing types). I call Properties such as Math.PI type variables. Then you can also talk about subtyping (instead of subclassing).

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Brendan Eich-3
In reply to this post by Axel Rauschmayer
On Jun 12, 2011, at 3:43 PM, Axel Rauschmayer wrote:

>>> (1) The syntax for private properties still is a bit clumsy, and @ feels like wasting a nice symbol, how about using private.foo instead of private(this).foo?
>>
>> No, you need private(other).foo or shorter for things like
>>
>>  class Point {
>>    constructor(x, y) {
>>      private x = x;
>>      private y = y;
>>    }
>>    equals(p) { return private(this).x === private(p).x && private(this).y === private(p).y; }
>>    ...
>>  }
>>
>> BTW, @ is hardly "wasted" as shorthand, since the above is way too long and also requires reifying private data as an object, which we do not want (I mean, I believe no one wants).
>
> What confuses me slightly is that it initially looks like private and public properties share the same namespace, but later don’t seem to. Maybe it would be better to make the different namespaces explicit:
>
>  class Point {
>    constructor(x, y) {
>      private @x = x;
>      private @y = y;

We hardly need private, then.

The point of the declarative forms that start with keywords such as private is to declare, not express. In the equals method I wrote originally:

  equals(p) { return @x === p@x && @y === p@y; }

@ is a prefix and infix operator in expressions.


>    }
>    equals(p) { return this.@x === p.@x && this.@y === p.@y; }

We've been over this ground. Why require . as well as @? The prefix form for this@ is a win too.


> Maybe something like the following would work, too:
>
> private.x = x;
> ...
> return this.private.x === p.private.x;

No, ES5 allows this.private, foo.private, etc. (reserved identifiers as property names).

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Brendan Eich-3
In reply to this post by Axel Rauschmayer
On Jun 12, 2011, at 3:49 PM, Axel Rauschmayer wrote:

>>> and the "static" keyword for defining class properties are welcome additions.
>>
>> Why "static" is the wrong word: there is nothing compile-time about the class properties. Classes are expressible (anonymous, even), as well as declarable in nested (generative) ways.
>>
>> Using "class" does not work if one wants nested classes, although the default that binds prototype properties for ExportableDefinitions including Declarations seems like exactly the wrong default: how often do you want class Outer { class Nested {} ... } to make Nested a property of Outer.prototype, instead of a class property (Outer.Nested)?
>>
>> Again, the grammatical retasking of certain Declarations to bind prototype properties (instead of lexical bindings in the class body, or perhaps class properties -- but perhaps not) seems like a mistake.
>
>
> Terminology-wise, I have always avoided the word “class” in JavaScript and used the word “type”, instead (with, roughly, constructors implementing types). I call Properties such as Math.PI type variables. Then you can also talk about subtyping (instead of subclassing).

Sorry, I can't agree with this. "type" is even more of a loaded word, and a misnomer. Math is not even a constructor, never mind a type!

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Axel Rauschmayer
In reply to this post by Brendan Eich-3
>> Something about classes in JS makes me sad, an emotional effect I can't explain fully. In part I fear the "lint brush" aspect I mentioned in the thread Irakli just followed up: class syntax will grow lots of hair over time. In part I think class is the wrong word, as cowboyd tweeted (see below).
>>
>> Mainly I think we are still finding class syntax, not just the keyword, a bit hard to fit to the prototypal pattern. The super keyword in limited expression forms is no problem. The extends and prototype "Heritage" clause in the class head is ok.
>>
>> The constructor flows from the prototype-methods-at-class-element-position design, but starts to rankle, if only because of the name's length. As you can see in my posts today, it seems to go downhill from there. And we're still trying to find a better syntax than the "static" keyword.
>
> Let's say we can make classes mean what we want. Per the agreement to promote them into Harmony with open issues, we are "close enough".
>
> But we still need to nail those open issues. This requires considering alternatives carefully and writing down everything pro and con. It'll be tedious work, without easy answers (at first). I'm game to do it here, although others may fear the Inbox load.
>
> Reflecting on classes in JS, at a high level I feel we are falling into the gravity well of a dying star. It could supernova, in which case we will be burned. Or it could black-hole and we'll get rent by tides before going somewhere else ;-).
>
> Ok, fun metaphor but I'm not totally kidding. The gravity well is created by the mass of "class expectations" from other languages, plus de-facto "prototypal" and other patterns in JS. Heavy.


Two observations:

- Object.create() seems to have started something truly prototypal in JavaScript that never quite got finished. If there was a way to bring more Self to JavaScript (instead of more Java, Python, or Ruby) when it comes to inheritance, I would be all for it, but it always sounded to me like most people don’t want that.

- What I find most difficult about the current way of doing inheritance is that the constructor "is" the type, while the prototype would be a much better choice.

var SkinnedMesh = THREE.Mesh <| {
  constructor(geometry, materials) {
    super.constructor(geometry, materials);
 
    this.identityMatrix = new THREE.Matrix4();
    this.bones = [];
    this.boneMatrices = [];
    ...
  }
 
  update(camera) {
    ...
    super.update();
  }
}

var sm = new SkinnedMesh(...);
sm instanceof SkinnedMesh // true


The only things that change from ES5 are:
- Adapting new and instanceof to accept objects (in addition to constructor functions)
- Some kind of proto operator (<| in the code above)
- super.foo(x,y) is syntactic sugar for Object.getPrototypeOf(SkinnedMesh).foo.call(this, x, y)
    - I have no idea how to get SkinnedMesh in there, but concise object literals make a similar proposal, so there must be a solution.
- The above obviously profits from anything offered by concise object literals (and in fact already uses the more compact way to write methods).

I hope this makes sense. A side benefit would be that type/class variables (such as Math.PI) would automatically be inherited to subtypes/subclasses.

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Peter Michaux
In reply to this post by Brendan Eich-3
On Sun, Jun 12, 2011 at 2:38 PM, Brendan Eich <[hidden email]> wrote:
>
> On Jun 12, 2011, at 2:22 PM, Axel Rauschmayer wrote:
> > Does anybody know what Brendan meant in this txjs talk with “Classes made it (Yay, I think? Why am I sad?)”? Is he ambivalent about the proposal? Is there anything he doesn’t like?

> You can just ask me ;-).
> Something about classes in JS makes me sad, an emotional effect I can't explain fully. In part I fear the "lint brush" aspect I mentioned in the thread Irakli just followed up: class syntax will grow lots of hair over time. In part I think class is the wrong word, as cowboyd tweeted (see below).

(For some reason I read that as "a cowboy in tweed" which seems wrong
and possibly a metaphor for wrapping "prototypes in classes".)

I think "class" is the wrong word also. If the syntax is just syntax
then ECMAScript still won't have any new kind of "class" thing that it
didn't have before.

One thing that worries me about using the word "class" is that folks
will think they are getting the same type of "class" that they have in
the other language the know/use/love. That won't be the case. It will
a misleading facade and lead to resentment.

Peter
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Juan Ignacio Dopazo
In reply to this post by Brendan Eich-3


On Sun, Jun 12, 2011 at 6:38 PM, Brendan Eich <[hidden email]> wrote:
On Jun 12, 2011, at 2:22 PM, Axel Rauschmayer wrote:

(1) The syntax for private properties still is a bit clumsy, and @ feels like wasting a nice symbol, how about using private.foo instead of private(this).foo?

No, you need private(other).foo or shorter for things like

 class Point {
   constructor(x, y) {
     private x = x;
     private y = y;
   }
   equals(p) { return private(this).x === private(p).x && private(this).y === private(p).y; }
   ...
 }
If I understand correctly the reason for needing private(this).x is because the private names proposal allows having a private name with the same name as a common property.

Also IIRC , this is a result of putting instance properties in the constructor. Because of that the private name lives in the scope of the constructor and not in the scope of the class. So would this be correct?

class Monster {
    private jump() {
        console.log('jump!');
    }
    constructor() {
        this.jump();
    }
}

Juan

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Brendan Eich-3
On Jun 12, 2011, at 4:54 PM, Juan Ignacio Dopazo wrote:

If I understand correctly the reason for needing private(this).x is because the private names proposal allows having a private name with the same name as a common property.

Whether private in class uses private name objects or some other unobservably-different implementation is not specified. It may not be observable even with reflection we can agree to put in the language any time soon.

Allen points out that a self-hosted debugger with VM-like stratification would want to peek at privates (as it would also at closure innards). In such scenarios, private name objects may be attractive, since they can yield to reflection (via .public, or without that substitution in a privileged "VM host" or "outer ring" trusted environment such as a debugger).

Closures for private vars have notable costs, discussed here recently, and so are not suitable in the foreseeable future. But to your point below, closures may be too closed if we are talking about the constructor.


Also IIRC , this is a result of putting instance properties in the constructor. Because of that the private name lives in the scope of the constructor and not in the scope of the class. So would this be correct?

class Monster {
    private jump() {
        console.log('jump!');
    }
    constructor() {
        this.jump();
    }
}

Not yet specified, but possible. Here an unobservable closure around the class (the power constructor pattern, IINM) could be used to hold the prototype-available, once per class evaluation, private bindings. Or perhaps private names on the prototype object could be used, but freeze would have to skip them.

I'm not sure classes should grow to have private class or prototype variables in ES.next. Mark stripped things down to help get classes in. The one reason I come back to them: private methods for common subroutining are frequent in practice. So YAGNI doesn't work. One can always closure- or module-wrap by hand; that's the counterargument.

/be


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Allen Wirfs-Brock
In reply to this post by Axel Rauschmayer

On Jun 12, 2011, at 4:13 PM, Axel Rauschmayer wrote:

Two observations:

- Object.create() seems to have started something truly prototypal in JavaScript that never quite got finished. If there was a way to bring more Self to JavaScript (instead of more Java, Python, or Ruby) when it comes to inheritance, I would be all for it, but it always sounded to me like most people don’t want that.

This is much of the motivation behind the enhanced object literal and <| proposals.  They are intended to be a more usable alternative to Object.create.



- What I find most difficult about the current way of doing inheritance is that the constructor "is" the type, while the prototype would be a much better choice.

I've been thinking a fair amount recently about prototypal inheritance in self versus what we do in JavaScript.  There are a couple things I've noted.  One is that while self started out as a deconstructed Smalltalk without classes, the evolution of the language and environment (like Smalltalk, it is hard to separate the two) ultimately took it to a place where you program in terms of abstractions that seem quite like Smalltalk classes. This seems roughly parallel to what we see occurring in both JS frameworks and ES.next. We find that we need a more concrete abstraction capability then naked prototype inheritance so we  use prototypal  inheritance to createsomething that is quite similar to Smalltalk classes but quite different from Java classes).

Another thing I've noted is that in creating its abstraction facilities, self makes extensive use of multiple inheritance.  One might argue that by starting with deconstructing classes self was able to successfully incorporate multiple inheritance into its abstraction model.  This is something that was never done successfully for classical Smalltalk. I don't know how successful self actually was in this regard as I've never done any actual self programming.  However, MI seems to have been used extensive in creating the self libraries and environment. 

AT first there seems to be a big difference between how self and JavaScript approach object creation.  In self, you create an object by copying and what copying means is actually the responsibility of the object that is being copied. By default copy means make a new object that directly inherits from the object it is copied from.   Prototype objects are what most typically get copied to create new instances.

So where in JavaScript we would say:
   var p = new Person();
to create an instance of a person in self one would say:
    p = ProtoPerson copy.

and the default definition of the copy method that is inherited from the top of the inheritance hierarchy is  the equivalent (in JavaScript terms) of:
    Object.prototype.copy = function() {return Object.create(this)};

in other words copy is does prototypal inheritance in self. 

Of course, this doesn't work very well if the prototype contains non-shareable mutable state.  This is accounted for by over-riding the copy in prototype objects to appropriately deal with such non-sharable state.  For example:
  ProtoPerson.copy = function () {
      let newPerson = super.copy();   //use super similarly to what is currently proposed for ES.next;
      newPerson.siblings = ProtoCollection.copy();  // assumes siblings is a mutable, non sharable property
      return newPerson;
  };

This is essentially the same thing you would do in a JavaScript Person constructor:
  function Person() {
       this.siblings = new Collection();
       return this
}

So, there is pretty much a directly correspondence between a self copy method and a JavaScript constructor function.  However, there is definitely a difference of emphasis seen here.  In self, it is the prototype object that is the focus of attention.  In traditional JavaScript it is the constructor object.


Allen  


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Axel Rauschmayer
> So, there is pretty much a directly correspondence between a self copy method and a JavaScript constructor function.  However, there is definitely a difference of emphasis seen here.  In self, it is the prototype object that is the focus of attention.  In traditional JavaScript it is the constructor object.

So you argue that a constructor C corresponds to an instance, a prototype P corresponds to a class (for lack of a better term). And instead of copying the prototypical instance, you “send the message ‘new’” to C. But then instanceof is still weird – the right hand side should be the prototype and not the constructor.

I’ve only got one use case for this, but “class methods” would also work better if they could be attached to the prototype (and subject to inheritance) instead of the constructor.

Take a root class Class that knows how to extend classes, including itself. For example:

var MySuperClass = Class.extend(...);
var MySubClass = MySuperClass.extend(...);

To implement something like this in ES5, you have to manually add the extend() method to each newly created class, because a constructor does not inherit methods that are attached to its super-constructor.

Well, this might be a largely academic discussion and class literals are probably a good enough compromise. But class literals being so similar to object literals, I like the idea of making do with just concise object literals and a proto operator.

Axel

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Allen Wirfs-Brock

On Jun 12, 2011, at 8:46 PM, Axel Rauschmayer wrote:

>> So, there is pretty much a directly correspondence between a self copy method and a JavaScript constructor function.  However, there is definitely a difference of emphasis seen here.  In self, it is the prototype object that is the focus of attention.  In traditional JavaScript it is the constructor object.
>
> So you argue that a constructor C corresponds to an instance, a prototype P corresponds to a class (for lack of a better term). And instead of copying the prototypical instance, you “send the message ‘new’” to C.


The correspondence is not quite that straight forward.  A prototype P, as used in self, does seem to frequently subsume the role of a class.  A constructor  generally corresponds to the copy method of such a prototype.


> But then instanceof is still weird – the right hand side should be the prototype and not the constructor.


Instanceof seems a artifact of trying to use constructors in the role of classes.  The corresponding operation to instanceof would be childOf: (meaning inherits from) but self doesn't appear to actually have this without getting a mirror (entering the reflection subsystem).  In Smalltalk class inclusion testing, while possible, was generally frowned upon.   Behavior testing  (send isFoo if you want to see if an object has Foo behavior) was the preferred pattern.

>
> I’ve only got one use case for this, but “class methods” would also work better if they could be attached to the prototype (and subject to inheritance) instead of the constructor.
>
> Take a root class Class that knows how to extend classes, including itself. For example:
>
> var MySuperClass = Class.extend(...);
> var MySubClass = MySuperClass.extend(...);
>
> To implement something like this in ES5, you have to manually add the extend() method to each newly created class, because a constructor does not inherit methods that are attached to its super-constructor.

This appears to be a situation where self would use multiple parents.


Allen
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Brendan Eich-3
In reply to this post by Axel Rauschmayer
On Jun 12, 2011, at 8:46 PM, Axel Rauschmayer wrote:

> I’ve only got one use case for this, but “class methods” would also work better if they could be attached to the prototype (and subject to inheritance) instead of the constructor.

We had a thread about this, because Ruby and CoffeeScript (which translates to JS and copies properties to do "constructor inheritance") both support class method inheritance.

Putting class methods on the prototype mixes up is-a relations, making the class constructor delegate to the class prototype. That breaks constructor is-a function in general. Better to have two parallel proto-chains, one from subclass prototype to superclass prototype, the other from subclass constructor to superclass constructor.

/be
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Axel Rauschmayer
In reply to this post by Allen Wirfs-Brock
Excellent points, thanks! Wasn’t aware that Smalltalk did duck typing, but it must make things much more generic.

Note: IIRC, Self calls its prototypical instances “prototypes”. What JavaScript calls a prototype (both the relation and the objects forming the right-hand sides of such a relation) is called a parent in Self. But that does not affect your arguments.

> The correspondence is not quite that straight forward.  A prototype P, as used in self, does seem to frequently subsume the role of a class.  A constructor  generally corresponds to the copy method of such a prototype.


Isn’t that the illusion that class literals aim to create? That a class is actually a single construct, an object C with a method construct() and that you can apply the new operator to that object? new C(x,y) would perform the following steps:

- Create a new instance o whose prototype is C.
- Invoke o.construct(x,y)

Maybe "initialize" would be a better name than "construct", then.

Couldn’t that illusion be turned into how things are actually done?

--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Kam Kasravi


On Jun 13, 2011, at 1:55 AM, Axel Rauschmayer <[hidden email]> wrote:

Excellent points, thanks! Wasn’t aware that Smalltalk did duck typing, but it must make things much more generic.

Note: IIRC, Self calls its prototypical instances “prototypes”. What JavaScript calls a prototype (both the relation and the objects forming the right-hand sides of such a relation) is called a parent in Self. But that does not affect your arguments.

The correspondence is not quite that straight forward.  A prototype P, as used in self, does seem to frequently subsume the role of a class.  A constructor  generally corresponds to the copy method of such a prototype.


Isn’t that the illusion that class literals aim to create? That a class is actually a single construct, an object C with a method construct() and that you can apply the new operator to that object? new C(x,y) would perform the following steps:

- Create a new instance o whose prototype is C.
- Invoke o.construct(x,y)

Maybe "initialize" would be a better name than "construct", then.

Couldn’t that illusion be turned into how things are actually done?

Indeed a number of frameworks use 'initialize' for their 'ctor'. I imagine this has been 
heavily discussed within TC39, but perhaps some of the rational has not made es-discuss. 
Certain unused ascii characters may be a candidate, for example I believe C++ uses ~ for 
their destructor, analogously a '^' for the ctor might be a good replacement 
given its semantics in a regex (start of pattern). 

class Monster {
  ^(health) {
    private health = health
  }
}

I believe this still renders the grammar LR(1), 
however given the symbols used for 'concise object literal extensions' 
this may be too much.



--
Dr. Axel Rauschmayer

[hidden email]
twitter.com/rauschma

home: rauschma.de
blog: 2ality.com



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Classes: suggestions for improvement

Juan Ignacio Dopazo
On Mon, Jun 13, 2011 at 12:01 PM, Kam Kasravi <[hidden email]> wrote:

On Jun 13, 2011, at 1:55 AM, Axel Rauschmayer <[hidden email]> wrote:

Indeed a number of frameworks use 'initialize' for their 'ctor'. I imagine this has been 
heavily discussed within TC39, but perhaps some of the rational has not made es-discuss. 

It was posted somewhere... The rationale is that 'constructor' is already a property of the prototype that points to the constructor function.

function Test() {}
(Test.prototype.constructor === Test) // true

It was chosen to replace 'new' because o.new() is correct under ES5.
 
 On Sun, Jun 12, 2011 at 10:17 PM, Brendan Eich <[hidden email]> wrote:

I'm not sure classes should grow to have private class or prototype variables in ES.next. Mark stripped things down to help get classes in. The one reason I come back to them: private methods for common subroutining are frequent in practice. So YAGNI doesn't work. One can always closure- or module-wrap by hand; that's the counterargument.

/be

I'm not sure that's a counterargument. The whole point of the classes proposal is to simplify the use of a common pattern. Private methods for subroutines are a very common use case.

Juan

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
12