I noted some open issues on "Classes with Trait Composition"

classic Classic list List threaded Threaded
78 messages Options
1234
Reply | Threaded
Open this post in threaded view
|

I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition#open_issues

This looks pretty good at a glance, but it's a lot, and it's new.

I have to say this reminds me of ES4 classes. That's neither bad nor good, but it's not just superficial, as far as I can tell (and I was reading specs then and now).

On the other hand, I'm in no rush to standardize something this complex and yet newly strawman-spec'ed and yet unimplemented. So we may as well take our time, learn from history, and go around the karmic wheel again for another few years...

I'm not against classes as a near-term objective, but in order to be near-term and not to unwind in committee, I believe they have to be dead simple and prototypal, with very few knobs, bells and whistles. Factoring out privacy and leaving constructor in charge of per-instance property setting, as it is in ES5, would IMHO help.

/be

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

Re: I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
On May 15, 2011, at 10:01 PM, Brendan Eich wrote:

http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition#open_issues

This looks pretty good at a glance, but it's a lot, and it's new.

Looking closer, I have to say something non-nit-picky that looks bad and smells like committee:


Two kinds of inheritance, depending on the dynamic type of the result of evaluating the //MemberExpression// on the right of ''extends''? That will be confusing.

Is the traits-composition way really needed in this proposal? If so, then please consider not abuse ''extends'' to mean ''compose'' depending on dynamic type of result of expression to its right.

/be



I have to say this reminds me of ES4 classes. That's neither bad nor good, but it's not just superficial, as far as I can tell (and I was reading specs then and now).

On the other hand, I'm in no rush to standardize something this complex and yet newly strawman-spec'ed and yet unimplemented. So we may as well take our time, learn from history, and go around the karmic wheel again for another few years...

I'm not against classes as a near-term objective, but in order to be near-term and not to unwind in committee, I believe they have to be dead simple and prototypal, with very few knobs, bells and whistles. Factoring out privacy and leaving constructor in charge of per-instance property setting, as it is in ES5, would IMHO help.

/be
_______________________________________________
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: I noted some open issues on "Classes with Trait Composition"

Dmitry Soshnikov
On 16.05.2011 10:49, Brendan Eich wrote:
On May 15, 2011, at 10:01 PM, Brendan Eich wrote:

http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition#open_issues

This looks pretty good at a glance, but it's a lot, and it's new.

Looking closer, I have to say something non-nit-picky that looks bad and smells like committee:


Two kinds of inheritance, depending on the dynamic type of the result of evaluating the //MemberExpression// on the right of ''extends''? That will be confusing.

Is the traits-composition way really needed in this proposal? If so, then please consider not abuse ''extends'' to mean ''compose'' depending on dynamic type of result of expression to its right.


Some simple examples of all use-cases would are needed I think.

Regarding `new` keyword for the constructor (aka initializer), after all, it als may be OK. E.g. Ruby uses `new` as exactly the method of a class -- Array.new, Object.new, etc. Though,  `constructor` is also good yeah.

Regarding two inheritance types, I think better to make nevertheless one inheritance type -- linear (by prototype chain). And to make additionally small reusable code units -- mixins or traits -- no matter. Thus, of course if they will also be delegation-based and not just copy-own-properties, then we automatically get a sort of multiple inheritance.

So again, better to have something like this:

class Bar extends Foo {
    includes Comparable
}

where Comparable is a trait/mixin. It becomes an ancestor of the instance (via some hidden-class), E.g.:

let bar = Bar.new(...args)

Then we have the following hierarchy:

bar -> HiddenClass -> Foo
           |
           |
       Comparable

I.e. beside the vertical ("tower") inheritance at each link of a chain we also have horizontal inheritance via mixins. Thus HiddenClass before going to its prototype chain, first try to find the property in the horizontal chain, i.e. in Comparable.

A simple object may also mix some functionality without using a class (if a user still needs pure prototype-based code reuse):

let bar = Object.mixing(Object.create(foo), Comparable);

Delegation-based mixins though can be implemented as a library using proxies (example: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/examples/mixin.js, implementation: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/src/mixin.js, notice I also used Object.new :)).
 
So we may actually understand what's going on by looking at the grammar, but nevertheless, if it's not hard, some simple examples would be nice.

Besides, I restore my previous syntactic proposal (Coffee/Ruby-like again) with a simple rule: (1) `this` evaluated in the class body is the class, (2) `this` evaluated in the instance method body is the instance. These two rules seems quite simple, not-overheaded, and the class definition looks like as an object initialiser. I used @ as a sugar, though it's not essential currently. Also, notice, I used `initialize` for `new` or `constructor`, since it seems more exactly describes the essence of the method: http://dmitrysoshnikov.com/scheme-on-coffee/class.html

Dmitry.


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

Re: I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
On May 16, 2011, at 4:54 AM, Dmitry A. Soshnikov wrote:

On 16.05.2011 10:49, Brendan Eich wrote:
On May 15, 2011, at 10:01 PM, Brendan Eich wrote:

http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition#open_issues

This looks pretty good at a glance, but it's a lot, and it's new.

Looking closer, I have to say something non-nit-picky that looks bad and smells like committee:


Two kinds of inheritance, depending on the dynamic type of the result of evaluating the //MemberExpression// on the right of ''extends''? That will be confusing.

Is the traits-composition way really needed in this proposal? If so, then please consider not abuse ''extends'' to mean ''compose'' depending on dynamic type of result of expression to its right.


Some simple examples of all use-cases would are needed I think.

Regarding `new` keyword for the constructor (aka initializer), after all, it als may be OK. E.g. Ruby uses `new` as exactly the method of a class -- Array.new, Object.new, etc. Though,  `constructor` is also good yeah.

My point is not to bikeshed, rather (a) to name existing prototype properties minimally, (b) to avoid preempting other names.

Good, bad, or in between, the prototypal pattern in JS for constructor C binds C.prototype.constructorr to C. It does not bind C.prototype.new.


Regarding two inheritance types, I think better to make nevertheless one inheritance type -- linear (by prototype chain). And to make additionally small reusable code units -- mixins or traits -- no matter. Thus, of course if they will also be delegation-based and not just copy-own-properties, then we automatically get a sort of multiple inheritance.

Self has multiple prototypes and you can use them for all kinds of inheritance patterns.




Delegation-based mixins though can be implemented as a library using proxies (example: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/examples/mixin.js, implementation: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/src/mixin.js, notice I also used Object.new :)).

Proxies are too costly, though. They always have a handler full of traps. The idea with classes is to capture prototypal inheritance as used today. The idea with traits is to make composition flexible, with fast failure on conflict and tools to rename around conflicts.

Putting classes and traitts together should be doable but it shouldn't use the same sytnax (extends) and it shouldn't require proxies.

/be

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

Re: I noted some open issues on "Classes with Trait Composition"

Dmitry Soshnikov
On 16.05.2011 19:02, Brendan Eich wrote:
On May 16, 2011, at 4:54 AM, Dmitry A. Soshnikov wrote:

On 16.05.2011 10:49, Brendan Eich wrote:
On May 15, 2011, at 10:01 PM, Brendan Eich wrote:

http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition#open_issues

This looks pretty good at a glance, but it's a lot, and it's new.

Looking closer, I have to say something non-nit-picky that looks bad and smells like committee:


Two kinds of inheritance, depending on the dynamic type of the result of evaluating the //MemberExpression// on the right of ''extends''? That will be confusing.

Is the traits-composition way really needed in this proposal? If so, then please consider not abuse ''extends'' to mean ''compose'' depending on dynamic type of result of expression to its right.


Some simple examples of all use-cases would are needed I think.

Regarding `new` keyword for the constructor (aka initializer), after all, it als may be OK. E.g. Ruby uses `new` as exactly the method of a class -- Array.new, Object.new, etc. Though,  `constructor` is also good yeah.

My point is not to bikeshed, rather (a) to name existing prototype properties minimally, (b) to avoid preempting other names.

Good, bad, or in between, the prototypal pattern in JS for constructor C binds C.prototype.constructorr to C. It does not bind C.prototype.new.


Yeah, agreed.


Regarding two inheritance types, I think better to make nevertheless one inheritance type -- linear (by prototype chain). And to make additionally small reusable code units -- mixins or traits -- no matter. Thus, of course if they will also be delegation-based and not just copy-own-properties, then we automatically get a sort of multiple inheritance.

Self has multiple prototypes and you can use them for all kinds of inheritance patterns.





Yes, I've heard about Self'ish multi-protos but don't know the lang, though have heard that JS has taken some things from it. Thanks for the paper.

Delegation-based mixins though can be implemented as a library using proxies (example: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/examples/mixin.js, implementation: https://github.com/DmitrySoshnikov/es-laboratory/blob/master/src/mixin.js, notice I also used Object.new :)).

Proxies are too costly, though. They always have a handler full of traps.

Yep, it was just an example.

The idea with classes is to capture prototypal inheritance as used today.

Yeah, classes are just a sugar in this case, the same as in Coffee, the same as in Python.

The idea with traits is to make composition flexible, with fast failure on conflict and tools to rename around conflicts.

Yes, but IMO the most interesting for programmers the ability to mix reusable code. The conflict-resolver is derived. And if to implement this conflict-resolve traits will have to be just things for static augmentation of objects with own properties, I think I choose better just mixins.

Dmitry.

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

Re: I noted some open issues on "Classes with Trait Composition"

Mark S. Miller-2
In reply to this post by Brendan Eich-3
On Sun, May 15, 2011 at 10:01 PM, Brendan Eich <[hidden email]> wrote:

That wiki page has no had extensive revisions in light of recent discussions with Brendan, Allen, Dave Herman, and Bob Nystrom. It derives from previous discussions with Allen, Bob, and Peter Hallam. I have tried to capture here as best as I could the consensus that has emerged from these discussions.

All this derives from earlier discussions that also included Waldemar, Alex Russell, Arv, and Tom Van Cutsem. And the experience of the Traceur project made a significant contribution. This has all had a long history so if I've left out some key contributors, please let me know, thanks.

 
This looks pretty good at a glance, but it's a lot, and it's new.

It's much less now! The main effect of all the recent feedback was to find opportunities to remove things. What remains is mostly just a way to express the familiar pattern by which JavaScript programmers manually express class-like semantics using prototypes. The result interoperates in both directions with such old code: a class can inherit from a traditional constructor function and vice versa.
 

I have to say this reminds me of ES4 classes. That's neither bad nor good, but it's not just superficial, as far as I can tell (and I was reading specs then and now).

It definitely had an influence. There were many things I liked about ES4 classes.
 

On the other hand, I'm in no rush to standardize something this complex and yet newly strawman-spec'ed and yet unimplemented. So we may as well take our time, learn from history, and go around the karmic wheel again for another few years...

I'm not against classes as a near-term objective, but in order to be near-term and not to unwind in committee, I believe they have to be dead simple and prototypal, with very few knobs, bells and whistles.

I am indeed proposing this as a near term objective. The usual caveats apply: we are asking the committee to approve the general shape presented by this strawman, with syntactic and semantic refinements expected to continue, for this as for all other proposals, after May.

Brendan, with all the simplifications since you posted this email, in your opinion, have we achieved the level of simplicity needed?

 
Factoring out privacy

Done.
 
and leaving constructor in charge of per-instance property setting, as it is in ES5,

Done.
 
would IMHO help.

Hope so ;).


I do understand that this page may be hard to appreciate without motivation and examples. I'm hoping these are coming soon.

--
    Cheers,
    --MarkM

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

Re: I noted some open issues on "Classes with Trait Composition"

Mark S. Miller-2
In reply to this post by Brendan Eich-3


On Sun, May 15, 2011 at 11:49 PM, Brendan Eich <[hidden email]> wrote:
On May 15, 2011, at 10:01 PM, Brendan Eich wrote:

http://wiki.ecmascript.org/doku.php?id=strawman:classes_with_trait_composition#open_issues

This looks pretty good at a glance, but it's a lot, and it's new.

Looking closer, I have to say something non-nit-picky that looks bad and smells like committee:


Two kinds of inheritance, depending on the dynamic type of the result of evaluating the //MemberExpression// on the right of ''extends''? That will be confusing.

This smell is actually just my fault; it did not derive from ideas arrived at in meetings. In any case, it is gone. "super(x, y);" is now always simply equivalent to "Superclass.call(this, x, y);", but as if using the original rather than the current binding of Function.prototype.call.

 

Is the traits-composition way really needed in this proposal? If so, then please consider not abuse ''extends'' to mean ''compose'' depending on dynamic type of result of expression to its right.

All dependencies on traits have been separated into a separate strawman, extending this one, but not to be proposed until after ES-next. The only inheritance in this one is traditional JS prototypal inheritance.

--
    Cheers,
    --MarkM

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

Re: I noted some open issues on "Classes with Trait Composition"

Mark S. Miller-2
In reply to this post by Dmitry Soshnikov
On Mon, May 16, 2011 at 4:54 AM, Dmitry A. Soshnikov <[hidden email]> wrote:
[...] 
Some simple examples of all use-cases would are needed I think.

Absolutely agree. I hope they are coming soon. Watch this space ;).

 

Regarding `new` keyword for the constructor (aka initializer), after all, it als may be OK. E.g. Ruby uses `new` as exactly the method of a class -- Array.new, Object.new, etc. Though,  `constructor` is also good yeah.

The history here is interesting. An earlier unreleased version of the Traceur compiler used "constructor". When we saw Allen's use of "new" in one of the object-literal-based class proposals, it seemed like a good idea so we switched to that. In light of Brendan's criticism, we realized we should return to "constructor" -- it's an elegant pun.
 

Regarding two inheritance types, I think better to make nevertheless one inheritance type -- linear (by prototype chain).

Done.

 
And to make additionally small reusable code units -- mixins or traits -- no matter. Thus, of course if they will also be delegation-based and not just copy-own-properties, then we automatically get a sort of multiple inheritance.

Gone. Or rather, postponed into a strawman that will not be proposed till after ES-next.

[...]

--
    Cheers,
    --MarkM

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

Re: I noted some open issues on "Classes with Trait Composition"

Bob Nystrom
In reply to this post by Brendan Eich-3


On Mon, May 16, 2011 at 8:02 AM, Brendan Eich <[hidden email]> wrote:
On May 16, 2011, at 4:54 AM, Dmitry A. Soshnikov wrote:
Regarding `new` keyword for the constructor (aka initializer), after all, it als may be OK. E.g. Ruby uses `new` as exactly the method of a class -- Array.new, Object.new, etc. Though,  `constructor` is also good yeah.

My point is not to bikeshed, rather (a) to name existing prototype properties minimally, (b) to avoid preempting other names.

Using "new" for the constructor is one of my favorite feature's of Allen's proposal. Things I like about it:

1. It's terse. Since almost every class defines a ctor, this is helpful. "constructor" is a mouthful and repeating the full class name (like in Java, C++, etc.) is redundant.
2. I think it's pretty clear to a user what's going on.
3. It avoids stealing a valid identifier. You can't define a method named "new" but "constructor" is a valid property name.


Good, bad, or in between, the prototypal pattern in JS for constructor C binds C.prototype.constructorr to C. It does not bind C.prototype.new.

That's true, but I hope for classes is to hide just that machinery. There's no mention of "prototype" when you define a property on that object inside a class but that's what happens under the hood.

My hope is that users should almost never need to know or care that C.prototype.constructor is bound to C. Instead, what I'd like is for "class" to be a valid expression inside a class member that evaluates to C. Instead of:

class math.geometry.Circle {
  class var pi = 3;
  new(radius) {
    this.radius = radius;
  }

  get circumference() {
    return this.radius * 2 * math.geometry.Circle.pi;
  }
}

Be able to do:

class math.geometry.Circle {
  class var pi = 3;
  new(radius) {
    this.radius = radius;
  }

  get circumference() {
    return this.radius * 2 * class.pi;  // <---
  }
}

- bob

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

Re: I noted some open issues on "Classes with Trait Composition"

Dave Herman
> Using "new" for the constructor is one of my favorite feature's of Allen's proposal. Things I like about it:
>
> 1. It's terse. Since almost every class defines a ctor, this is helpful. "constructor" is a mouthful and repeating the full class name (like in Java, C++, etc.) is redundant.
> 2. I think it's pretty clear to a user what's going on.
> 3. It avoids stealing a valid identifier. You can't define a method named "new" but "constructor" is a valid property name.

Yes you can:

    var obj = {
        new: function() { print("hey what's up") }
    }

To my mind, this slightly weakens the case for |new| over |constructor|. You'd be special-casing the syntax *not* to create a property called "new" even though in object literals it does.

But I'm somewhat divided about this particular issue. You're right that the longer name hurts both for writing and reading. In both cases, the name is being special-cased (in either case, there's something special going on: the function defines the call and construct behavior of the class's constructor function, and both the instance *and* the prototype are given a property called |constructor|). But arguably there's something slightly less surprising about giving the special-case semantics to a reserved word, and of course only in the context of a class body. And yet, as I said above, there is something slightly weird about *not* creating a property called "new" when using the keyword |new|. (I think it would be a bad idea to have it create *both* a property called |constructor| *and* a property called |new|.)

Dave

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

Re: I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
In reply to this post by Bob Nystrom
On May 18, 2011, at 10:58 AM, Bob Nystrom wrote:

On Mon, May 16, 2011 at 8:02 AM, Brendan Eich <[hidden email]> wrote:
On May 16, 2011, at 4:54 AM, Dmitry A. Soshnikov wrote:
Regarding `new` keyword for the constructor (aka initializer), after all, it als may be OK. E.g. Ruby uses `new` as exactly the method of a class -- Array.new, Object.new, etc. Though,  `constructor` is also good yeah.

My point is not to bikeshed, rather (a) to name existing prototype properties minimally, (b) to avoid preempting other names.

Using "new" for the constructor is one of my favorite feature's of Allen's proposal. Things I like about it:

1. It's terse. Since almost every class defines a ctor, this is helpful. "constructor" is a mouthful and repeating the full class name (like in Java, C++, etc.) is redundant.

The whole of class declaration is a mouthful. 'function' and 'prototype' are overlong too. We can try for conciseness in this one corner but it doesn't help in general. I think we need to weight the whole syntax and see where the verbosity *and other* pain points are in practice.


2. I think it's pretty clear to a user what's going on.

Same with 'constructor', and that property must exist somehow. Why not be explicit and avoid having two names for one prototype property?


3. It avoids stealing a valid identifier. You can't define a method named "new" but "constructor" is a valid property name.

3 is false in ES5. Reserved identifiers are valid property names. This is implemented in all the ES5-supporting browsers.

/be

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

Re: I noted some open issues on "Classes with Trait Composition"

Bob Nystrom
On Wed, May 18, 2011 at 11:48 AM, Brendan Eich <[hidden email]> wrote:
The whole of class declaration is a mouthful. 'function' and 'prototype' are overlong too.

Agreed. One of the reasons I'm really excited about this proposal is that it addresses those:

// old and busted
function SomeClass() {}; SomeClass.prototype.someMethod = function(arg) { ... }

// new hotness
class SomeClass { someMethod(arg) { ... } }


We can try for conciseness in this one corner but it doesn't help in general. I think we need to weight the whole syntax and see where the verbosity *and other* pain points are in practice.

Sure. I'm not stuck on "new", but in the chunks of sample code I've put together using "constructor" (which is what Traceur uses/did use for a good while) it did actually stick out as a syntactic wart, at least to me.

Same with 'constructor', and that property must exist somehow. Why not be explicit and avoid having two names for one prototype property?

3 is false in ES5. Reserved identifiers are valid property names. This is implemented in all the ES5-supporting browsers.

Ah, my mistake. These are both fair points. It's too bad "constructor" is such a long word.

In the interests of considering all possibilities, one option would be to use no name at all for the constructor:

class Point {
  (x, y) {
    this.x = x;
    this.y = y;
  }
}

I find that simultaneously delightfully lightweight and terrifyingly obscure.

- bob


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

Re: I noted some open issues on "Classes with Trait Composition"

Rick Waldron
Just sort of curious... Given the following: 

// old and busted
function SomeClass() {}; SomeClass.prototype.someMethod = function(arg) { ... }

// new hotness
class SomeClass { someMethod(arg) { ... } }

In the second form, how would I denote a method that is defined as an own property? Additionally, how would something like the following be handled?

function Ctor({
    this.method function({
        return "own property";  
    };
    return this;
}

Ctor.prototype.method function({
    return "instance property";   
};
    
var new Ctor();

console.log(
    c.method(// "own property"
);


Thanks in advance :)

Rick



On Wed, May 18, 2011 at 3:10 PM, Bob Nystrom <[hidden email]> wrote:
On Wed, May 18, 2011 at 11:48 AM, Brendan Eich <[hidden email]> wrote:
The whole of class declaration is a mouthful. 'function' and 'prototype' are overlong too.

Agreed. One of the reasons I'm really excited about this proposal is that it addresses those:

// old and busted
function SomeClass() {}; SomeClass.prototype.someMethod = function(arg) { ... }

// new hotness
class SomeClass { someMethod(arg) { ... } }


We can try for conciseness in this one corner but it doesn't help in general. I think we need to weight the whole syntax and see where the verbosity *and other* pain points are in practice.

Sure. I'm not stuck on "new", but in the chunks of sample code I've put together using "constructor" (which is what Traceur uses/did use for a good while) it did actually stick out as a syntactic wart, at least to me.

Same with 'constructor', and that property must exist somehow. Why not be explicit and avoid having two names for one prototype property?

3 is false in ES5. Reserved identifiers are valid property names. This is implemented in all the ES5-supporting browsers.

Ah, my mistake. These are both fair points. It's too bad "constructor" is such a long word.

In the interests of considering all possibilities, one option would be to use no name at all for the constructor:

class Point {
  (x, y) {
    this.x = x;
    this.y = y;
  }
}

I find that simultaneously delightfully lightweight and terrifyingly obscure.

- bob


_______________________________________________
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: I noted some open issues on "Classes with Trait Composition"

Bob Nystrom
I believe it would be something like:

class Ctor {
  public method() {
    return "own property";
  }

  method() {
    return "instance property";
  }
}

By default, members within a class body are declared on the prototype. Prefixing it with public places it on the new instance. Using public for this isn't carved in stone yet, but <some keyword> means "place the member on the new instance" and that prefix can be applied to any kind of member: method, variable, constant, etc.

- bob

On Wed, May 18, 2011 at 5:07 PM, Rick Waldron <[hidden email]> wrote:
Just sort of curious... Given the following: 

// old and busted
function SomeClass() {}; SomeClass.prototype.someMethod = function(arg) { ... }

// new hotness
class SomeClass { someMethod(arg) { ... } }

In the second form, how would I denote a method that is defined as an own property? Additionally, how would something like the following be handled?

function Ctor({
    this.method function({
        return "own property";  
    };
    return this;
}

Ctor.prototype.method function({
    return "instance property";   
};
    
var new Ctor();

console.log(
    c.method(// "own property"
);


Thanks in advance :)

Rick



On Wed, May 18, 2011 at 3:10 PM, Bob Nystrom <[hidden email]> wrote:
On Wed, May 18, 2011 at 11:48 AM, Brendan Eich <[hidden email]> wrote:
The whole of class declaration is a mouthful. 'function' and 'prototype' are overlong too.

Agreed. One of the reasons I'm really excited about this proposal is that it addresses those:

// old and busted
function SomeClass() {}; SomeClass.prototype.someMethod = function(arg) { ... }

// new hotness
class SomeClass { someMethod(arg) { ... } }


We can try for conciseness in this one corner but it doesn't help in general. I think we need to weight the whole syntax and see where the verbosity *and other* pain points are in practice.

Sure. I'm not stuck on "new", but in the chunks of sample code I've put together using "constructor" (which is what Traceur uses/did use for a good while) it did actually stick out as a syntactic wart, at least to me.

Same with 'constructor', and that property must exist somehow. Why not be explicit and avoid having two names for one prototype property?

3 is false in ES5. Reserved identifiers are valid property names. This is implemented in all the ES5-supporting browsers.

Ah, my mistake. These are both fair points. It's too bad "constructor" is such a long word.

In the interests of considering all possibilities, one option would be to use no name at all for the constructor:

class Point {
  (x, y) {
    this.x = x;
    this.y = y;
  }
}

I find that simultaneously delightfully lightweight and terrifyingly obscure.

- bob


_______________________________________________
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: I noted some open issues on "Classes with Trait Composition"

Mark S. Miller-2
On Wed, May 18, 2011 at 5:17 PM, Bob Nystrom <[hidden email]> wrote:
I believe it would be something like:

class Ctor {
  public method() {
    return "own property";
  }

  method() {
    return "instance property";
  }
}

By default, members within a class body are declared on the prototype. Prefixing it with public places it on the new instance. Using public for this isn't carved in stone yet, but <some keyword> means "place the member on the new instance" and that prefix can be applied to any kind of member: method, variable, constant, etc.

Not quite. Per-instance member initialization only happens in the constructor, because the values of per-instance properties is generally data dependent on constructor parameters. The "public" (or whatever) and "private" declarations only prefix ForwardDeclarations, which are generally just comma separated lists of identifiers. The initialization in the constructor happens in the traditional ES5 imperative manner. Also, the public list is optional. It serves only a documentary purpose. So....

 class Ctor {
  public method; // optional forward declaration of own property

  method() {
    return "instance property";
  }

  constructor() {
    this.method = function() {
      return "own property";
    };
  }
}
   

 

--
    Cheers,
    --MarkM

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

Re: I noted some open issues on "Classes with Trait Composition"

Bob Nystrom


On Wed, May 18, 2011 at 5:51 PM, Mark S. Miller <[hidden email]> wrote:
On Wed, May 18, 2011 at 5:17 PM, Bob Nystrom <[hidden email]> wrote:
I believe it would be something like:

class Ctor {
  public method() {
    return "own property";
  }

  method() {
    return "instance property";
  }
}

By default, members within a class body are declared on the prototype. Prefixing it with public places it on the new instance. Using public for this isn't carved in stone yet, but <some keyword> means "place the member on the new instance" and that prefix can be applied to any kind of member: method, variable, constant, etc.

Not quite. Per-instance member initialization only happens in the constructor, because the values of per-instance properties is generally data dependent on constructor parameters. The "public" (or whatever) and "private" declarations only prefix ForwardDeclarations, which are generally just comma separated lists of identifiers. The initialization in the constructor happens in the traditional ES5 imperative manner. Also, the public list is optional. It serves only a documentary purpose. So....

 class Ctor {
  public method; // optional forward declaration of own property

  method() {
    return "instance property";
  }

  constructor() {
    this.method = function() {
      return "own property";
    };
  }
}

Ah, OK. While it isn't necessary, it would be really convenient to be able to create per-instance properties by providing an initializer in the class body if those properties don't depend on "this" or ctor params:

class Point {
  public x = 0, y = 0;
}

let p = new Point();
p.x; // 0

- bob


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

Re: I noted some open issues on "Classes with Trait Composition"

Brendan Eich-3
On May 18, 2011, at 5:57 PM, Bob Nystrom wrote:

class Point {
  public x = 0, y = 0;
}

let p = new Point();
p.x; // 0

This is pretty rare, in my experience. A hard case? If the constructor does set x and y from parameters, then you have double-initialization. If some properties are non-writable, you can't do this. YAGNI?

/be


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

Re: I noted some open issues on "Classes with Trait Composition"

Mark S. Miller-2


On Wed, May 18, 2011 at 6:29 PM, Brendan Eich <[hidden email]> wrote:
On May 18, 2011, at 5:57 PM, Bob Nystrom wrote:

class Point {
  public x = 0, y = 0;
}

let p = new Point();
p.x; // 0

This is pretty rare, in my experience. A hard case? If the constructor does set x and y from parameters, then you have double-initialization. If some properties are non-writable, you can't do this. YAGNI?

+1. If you're gonna initialize them somewhere, why not always do so in the constructor and avoid special cases?

 

/be




--
    Cheers,
    --MarkM

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

Re: I noted some open issues on "Classes with Trait Composition"

Juan Ignacio Dopazo

On Wed, May 18, 2011 at 4:10 PM, Bob Nystrom <[hidden email]> wrote:
On Wed, May 18, 2011 at 11:48 AM, Brendan Eich <[hidden email]> wrote:
The whole of class declaration is a mouthful. 'function' and 'prototype' are overlong too.

Sure. I'm not stuck on "new", but in the chunks of sample code I've put together using "constructor" (which is what Traceur uses/did use for a good while) it did actually stick out as a syntactic wart, at least to me.

Same with 'constructor', and that property must exist somehow. Why not be explicit and avoid having two names for one prototype property?

3 is false in ES5. Reserved identifiers are valid property names. This is implemented in all the ES5-supporting browsers.

Ah, my mistake. These are both fair points. It's too bad "constructor" is such a long word.

Nowadays most libraries that implement some sort of class wrapping use lengthy names for the constructor and it's not that bad.

Mootools
var Cat = new Class({
    initialize: function(name){
        this.name = name;
    }
});

Prototype
var Cat = Class.create({
    initialize: function(name){
        this.name = name;
    }
});

Dojo
var Cat = dojo.declare(null, {
    constructor: function(name){
        this.name = name;
    }
});

YUI
var Cat = Y.Base.create('cat', null, [], {
    initializer: function(name){
        this.name = name;
    }
});


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

Re: I noted some open issues on "Classes with Trait Composition"

Andreas Rossberg-4
In reply to this post by Mark S. Miller-2
My apologies if this has been discussed to death before -- well,
actually, I'd be surprised if it hasn't (pointers would be welcome).

I think it is worth noting that the baroque notation for defining
constructors that we see in the C++ / Java / C# world primarily is an
artefact of the desire to allow multiple constructors with overloading
in those languages. We don't have that issue in JS, so I wonder why we
cannot go for something more elegant? There is precedent in other
OOPLs (off the top of my head, e.g. Scala and OCaml) for putting the
constructor arguments on the class head directly, and executing the
class body like a block when the constructor is invoked. AFAICS:

-- This approach is significantly slimmer (and, I'd argue, more
readable) than the discussed alternatives, without needing any
keywords:

class Point(x0, y0) {
  public x = x0
  public y = y0
}

-- It naturally allows what Bob was suggesting:

class Point {  // no argument list would be shorthand for (), just
like when invoking new
  public x = 0
  public y = 0
}

-- It avoids additional hoops with initializing const attributes:

class ImmutablePoint(x0, y0) {
  const x = x0  // just like elsewhere
  const y = y0
}

-- The constructor arguments naturally are in the scope of the entire
object, so often you do not even need to introduce explicit (private)
fields to store them:

class Point(x, y) {
  public function abs() { return Math.sqrt(x*x, y*y) }
}

/Andreas


On 19 May 2011 03:31, Mark S. Miller <[hidden email]> wrote:

>
>
> On Wed, May 18, 2011 at 6:29 PM, Brendan Eich <[hidden email]> wrote:
>>
>> On May 18, 2011, at 5:57 PM, Bob Nystrom wrote:
>>
>> class Point {
>>   public x = 0, y = 0;
>> }
>> let p = new Point();
>> p.x; // 0
>>
>> This is pretty rare, in my experience. A hard case? If the constructor
>> does set x and y from parameters, then you have double-initialization. If
>> some properties are non-writable, you can't do this. YAGNI?
>
> +1. If you're gonna initialize them somewhere, why not always do so in the
> constructor and avoid special cases?
>
>>
>> /be
>
>
>
> --
>     Cheers,
>     --MarkM
>
> _______________________________________________
> 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
1234