about lightweight traits

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

about lightweight traits

Andrea Giammarchi-2
Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?

I find that an anty pattern.

I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.

Thoughts? Thanks!

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

Re: about lightweight traits

Mark S. Miller-2
On Thu, Feb 12, 2015 at 8:35 AM, Andrea Giammarchi <[hidden email]> wrote:
Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?

I do. But I am in no rush. Classes need to grow in several other directions first, and many of these are much higher priority. If classes can no longer be extended to serve as traits, I am fine with dropping this as well.

 

I find that an anty pattern.

I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.

Thoughts? Thanks!

See http://traitsjs.org and previous stale strawmen



--
    Cheers,
    --MarkM

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

Re: about lightweight traits

Sébastien Cevey
In reply to this post by Andrea Giammarchi-2
I would agree.

How would you use classes as traits -- are you talking about multiple inheritance? Or flattened to a linear inheritance model?

On 12 February 2015 at 16:35, Andrea Giammarchi <[hidden email]> wrote:
Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?

I find that an anty pattern.

I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.

Thoughts? Thanks!

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




--
Sébastien Cevey
Software Developer


Visit theguardian.com. On your mobile and tablet, download the Guardian iPhone and Android apps theguardian.com/guardianapp and our tablet editions theguardian.com/editions.  Save up to 57% by subscribing to the Guardian and Observer - choose the papers you want and get full digital access.  Visit subscribe.theguardian.com

This e-mail and all attachments are confidential and may also be privileged. If you are not the named recipient, please notify the sender and delete the e-mail and all attachments immediately. Do not disclose the contents to another person. You may not use the information for any purpose, or store, or copy, it in any way.  Guardian News & Media Limited is not liable for any computer viruses or other material transmitted with or as part of this e-mail. You should employ virus checking software.
 
Guardian News & Media Limited is a member of Guardian Media Group plc. Registered Office: PO Box 68164, Kings Place, 90 York Way, London, N1P 2AP.  Registered in England Number 908396



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

Re: about lightweight traits

Luke Scott
In reply to this post by Andrea Giammarchi-2

On Feb 12, 2015, at 8:35 AM, Andrea Giammarchi <[hidden email]> wrote:

Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?

I find that an anty pattern.

I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.

Thoughts? Thanks!

I would agree with that. I had a trait implementation that used classes as traits, and it caused a lot of problems, especially since classes have constructors. Traits should not have constructors. I have since updated my implementation to use plain objects.


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

Re: about lightweight traits

Andrea Giammarchi-2
this thousand times ... Traits as class makes no sense to me indeed and Mark example shows plain objects passed as Trait.create ... that works just fine, except some trait initialization, which should not be a constructor, could be used too.

Is there any other language that uses same classical OOP classes as traits too? It really does not feel right to me.

Btw, reason I'm asking is because somebody else asked, I'm really OK to not rush and wait to see how it goes when it's the right time.

Best Regards

On Thu, Feb 12, 2015 at 6:32 PM, Luke Scott <[hidden email]> wrote:

On Feb 12, 2015, at 8:35 AM, Andrea Giammarchi <[hidden email]> wrote:

Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?

I find that an anty pattern.

I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.

Thoughts? Thanks!

I would agree with that. I had a trait implementation that used classes as traits, and it caused a lot of problems, especially since classes have constructors. Traits should not have constructors. I have since updated my implementation to use plain objects.


_______________________________________________
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: about lightweight traits

Luke Scott

On Feb 12, 2015, at 10:27 AM, Andrea Giammarchi <[hidden email]> wrote:

this thousand times ... Traits as class makes no sense to me indeed and Mark example shows plain objects passed as Trait.create ... that works just fine, except some trait initialization, which should not be a constructor, could be used too.

Is there any other language that uses same classical OOP classes as traits too? It really does not feel right to me.

Btw, reason I'm asking is because somebody else asked, I'm really OK to not rush and wait to see how it goes when it's the right time.

Best Regards

On Thu, Feb 12, 2015 at 6:32 PM, Luke Scott <[hidden email]> wrote:

I would agree with that. I had a trait implementation that used classes as traits, and it caused a lot of problems, especially since classes have constructors. Traits should not have constructors. I have since updated my implementation to use plain objects.


Based on the gist I provided, this is how I would envision the ES7 version looking like:


trait Trait1 {
  method1() {}
}

trait Trait2 {
  method2() {}
}

trait Trait3 {
  mixin Trait2;

  method3() {}
}

Trait3 hasTrait Trait2 // true
Trait3 hasTrait Trait1 // false

class Foo {
  mixin Trait1;
}

Foo hasTrait Trait1 // true
Foo hasTrait Trait2 // false

class Foo2 extends Foo {}

Foo2 hasTrait Trait1 // true
Foo2 hasTrait Trait2 // false

class Foo3 extends Foo {
  mixin Trait2;
}

Foo3 hasTrait Trait1 // true
Foo3 hasTrait Trait2 // true

class Bar {
  mixin Trait3;
}

Bar hasTrait Trait1 // false
Bar hasTrait Trait2 // true
Bar hasTrait Trait3 // true


As far as conflict resolution goes, you could go by trait order (last one wins), or simply throw an exception when mixing in two traits with the same methods. A conflict would look like this:

trait Trait1 {
  someMethod()
}

trait Trait2 {
  someMethod()
}

class Foo {
  mixin Trait1, Trait2;
}

OR

class Foo {
  mixin Trait1
  mixin Trait2;
}


But this would not be a conflict:


trait Trait1 {
  someMethod()
}

trait Trait2 {
  mixin Trait1;
  someMethod() // Override method from Trait1
}

class Foo {
  mixin Trait2;
}


PHP has traits, but has a way to resolve conflicts by specifying which method should be used. I would keep it simple and make conflicts an error outright or last one wins. Most use cases for traits is including functionality that can’t be inherited where you would have to copy and paste methods otherwise.


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

Re: about lightweight traits

Matthew Robb
In reply to this post by Sébastien Cevey
When I brought this up my thoughts were to have the classes flattened to a linear inheritance model. Yeah this means an ownProp copy from the constructor for statics and the prototype for instance onto methods. That might be a limitation but currently class syntax is javascript's nicest way to describe behavior units.


- Matthew Robb

On Thu, Feb 12, 2015 at 12:32 PM, Sébastien Cevey <[hidden email]> wrote:
I would agree.

How would you use classes as traits -- are you talking about multiple inheritance? Or flattened to a linear inheritance model?

On 12 February 2015 at 16:35, Andrea Giammarchi <[hidden email]> wrote:
Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?

I find that an anty pattern.

I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.

Thoughts? Thanks!

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




--
Sébastien Cevey
Software Developer


Visit theguardian.com. On your mobile and tablet, download the Guardian iPhone and Android apps theguardian.com/guardianapp and our tablet editions theguardian.com/editions.  Save up to 57% by subscribing to the Guardian and Observer - choose the papers you want and get full digital access.  Visit subscribe.theguardian.com

This e-mail and all attachments are confidential and may also be privileged. If you are not the named recipient, please notify the sender and delete the e-mail and all attachments immediately. Do not disclose the contents to another person. You may not use the information for any purpose, or store, or copy, it in any way.  Guardian News & Media Limited is not liable for any computer viruses or other material transmitted with or as part of this e-mail. You should employ virus checking software.
 
Guardian News & Media Limited is a member of Guardian Media Group plc. Registered Office: PO Box 68164, Kings Place, 90 York Way, London, N1P 2AP.  Registered in England Number 908396



_______________________________________________
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: about lightweight traits

Alex Russell-4
In reply to this post by Andrea Giammarchi-2
Traits as class make perfect sense when you consider that classes are functions and so are traits.

On Thu, Feb 12, 2015 at 10:27 AM, Andrea Giammarchi <[hidden email]> wrote:
this thousand times ... Traits as class makes no sense to me indeed and Mark example shows plain objects passed as Trait.create ... that works just fine, except some trait initialization, which should not be a constructor, could be used too.

Is there any other language that uses same classical OOP classes as traits too? It really does not feel right to me.

Btw, reason I'm asking is because somebody else asked, I'm really OK to not rush and wait to see how it goes when it's the right time.

Best Regards

On Thu, Feb 12, 2015 at 6:32 PM, Luke Scott <[hidden email]> wrote:

On Feb 12, 2015, at 8:35 AM, Andrea Giammarchi <[hidden email]> wrote:

Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?

I find that an anty pattern.

I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.

Thoughts? Thanks!

I would agree with that. I had a trait implementation that used classes as traits, and it caused a lot of problems, especially since classes have constructors. Traits should not have constructors. I have since updated my implementation to use plain objects.


_______________________________________________
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



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

RE: about lightweight traits

Andrea Giammarchi-2
So you are saying we can just forget about extends keyword and use mixin instead for everything, right?

From: [hidden email]
Sent: ‎12/‎02/‎2015 20:05
To: [hidden email]
Cc: [hidden email]; [hidden email]
Subject: Re: about lightweight traits

Traits as class make perfect sense when you consider that classes are functions and so are traits.

On Thu, Feb 12, 2015 at 10:27 AM, Andrea Giammarchi <[hidden email]> wrote:
this thousand times ... Traits as class makes no sense to me indeed and Mark example shows plain objects passed as Trait.create ... that works just fine, except some trait initialization, which should not be a constructor, could be used too.

Is there any other language that uses same classical OOP classes as traits too? It really does not feel right to me.

Btw, reason I'm asking is because somebody else asked, I'm really OK to not rush and wait to see how it goes when it's the right time.

Best Regards

On Thu, Feb 12, 2015 at 6:32 PM, Luke Scott <[hidden email]> wrote:

On Feb 12, 2015, at 8:35 AM, Andrea Giammarchi <[hidden email]> wrote:

Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?

I find that an anty pattern.

I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.

Thoughts? Thanks!

I would agree with that. I had a trait implementation that used classes as traits, and it caused a lot of problems, especially since classes have constructors. Traits should not have constructors. I have since updated my implementation to use plain objects.


_______________________________________________
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



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

Re: about lightweight traits

Benjamin Gruenbaum-2
In reply to this post by Andrea Giammarchi-2
Why does ES even need traits?
The only aspect they can help with here is the type system we don't have yet.

We have `Object.assign` that works fantastically for most classic trait use cases.

> On Feb 12, 2015, at 18:35, Andrea Giammarchi <[hidden email]> wrote:
>
> Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?
>
> I find that an anty pattern.
>
> I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.
>
> Thoughts? Thanks!
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

RE: about lightweight traits

Domenic Denicola
From: es-discuss [mailto:[hidden email]] On Behalf Of Benjamin Gruenbaum

> We have `Object.assign` that works fantastically for most classic trait use cases.

Well, actually, it works extremely poorly. The old (now dead or deferred) `Object.mixin`, once called `Object.define`, is a better fit. But it still fails to account for a couple things, off the top of my head:

- Being able to add custom initialization logic to the class constructor when "mixing in" a trait. You can construct a custom protocol around this, but (a) that means the class you're mixing in to needs to be aware of the protocol; (b) everyone needs to agree on a protocol across the ecosystem.
- Pretty much anything to do with private state doesn't work anymore.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: about lightweight traits

Andrea Giammarchi-2
In reply to this post by Benjamin Gruenbaum-2
`Object.assign` is good only to define defaults properties, since it does not even understand getters and setters, it's really a poor option for anything trait related.

`Object.assign` is an ES6 introduction based on ES3 assumptions, not even sure why someone would consider it for traits.

Moreover, initialization on `new ClassWithTraits` is something we'll eventually have to agree about, and here `assign` is poor indeed as Domenic said already.

On top of that, `instanceof SomeTrait` makes again no sense to me, 'cause that's **class** related and not behavior related, hence my idea that classes as traits are somehow misleading, confusing, or a mistake.

These two cannot be the same, otherwise we need to agree on which one is redundant ( and I already have an idea which one, now flagship of the incoming standard, would loose "the competition" )




On Thu, Feb 12, 2015 at 9:08 PM, Benjamin Gruenbaum <[hidden email]> wrote:
Why does ES even need traits?
The only aspect they can help with here is the type system we don't have yet.

We have `Object.assign` that works fantastically for most classic trait use cases.

> On Feb 12, 2015, at 18:35, Andrea Giammarchi <[hidden email]> wrote:
>
> Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?
>
> I find that an anty pattern.
>
> I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.
>
> Thoughts? Thanks!


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

Re: about lightweight traits

Luke Scott
In reply to this post by Andrea Giammarchi-2
Traits are different than classical inheritance. They simply copy functionality into a class as if the method was actually defined in the class. It isn’t inheritance. It allows you to DRY.

A real world example in my ES6 project:

- Node
- Element extends Node
- Field extends Element
- TextField extends Element
- Select extends Element, mixin Parent
- Option extends Element
- Fieldset extends Element, mixin Parent

In this case (subset of my class structure) a Fieldset has child Nodes/Elements/Fields. A Field and TextField does not have children. Yet, Select has specific child nodes. I use a trait to mixin the Parent trait to reuse functionality. Select is a parent because it has the trait, but the parent class Field is not a parent. In my case it makes no sense to re-implement that in Select, especially when having the Parent trait means something when building something like a lookup table.

I think it’s important to note that a trait knows very little of the class that implements it. For example I may mixin Parent into Select or Fieldset, but I restrict myself to methods found in Node (my base class) to be able to use the trait in any situation. If I need functionality from another trait, I mixin the other trait to make one trait.

On Feb 12, 2015, at 12:07 PM, Andrea Giammarchi <[hidden email]> wrote:

So you are saying we can just forget about extends keyword and use mixin instead for everything, right?

From: [hidden email]
Sent: ‎12/‎02/‎2015 20:05
To: [hidden email]
Cc: [hidden email]; [hidden email]
Subject: Re: about lightweight traits

Traits as class make perfect sense when you consider that classes are functions and so are traits.

On Thu, Feb 12, 2015 at 10:27 AM, Andrea Giammarchi <[hidden email]> wrote:
this thousand times ... Traits as class makes no sense to me indeed and Mark example shows plain objects passed as Trait.create ... that works just fine, except some trait initialization, which should not be a constructor, could be used too.

Is there any other language that uses same classical OOP classes as traits too? It really does not feel right to me.

Btw, reason I'm asking is because somebody else asked, I'm really OK to not rush and wait to see how it goes when it's the right time.

Best Regards

On Thu, Feb 12, 2015 at 6:32 PM, Luke Scott <[hidden email]> wrote:

On Feb 12, 2015, at 8:35 AM, Andrea Giammarchi <[hidden email]> wrote:

Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?

I find that an anty pattern.

I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.

Thoughts? Thanks!

I would agree with that. I had a trait implementation that used classes as traits, and it caused a lot of problems, especially since classes have constructors. Traits should not have constructors. I have since updated my implementation to use plain objects.


_______________________________________________
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




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

Re: about lightweight traits

Luke Scott
In reply to this post by Domenic Denicola

> On Feb 12, 2015, at 12:11 PM, Domenic Denicola <[hidden email]> wrote:
>
> From: es-discuss [mailto:[hidden email]] On Behalf Of Benjamin Gruenbaum
>
>> We have `Object.assign` that works fantastically for most classic trait use cases.
>
> Well, actually, it works extremely poorly. The old (now dead or deferred) `Object.mixin`, once called `Object.define`, is a better fit. But it still fails to account for a couple things, off the top of my head:
>
> - Being able to add custom initialization logic to the class constructor when "mixing in" a trait. You can construct a custom protocol around this, but (a) that means the class you're mixing in to needs to be aware of the protocol; (b) everyone needs to agree on a protocol across the ecosystem.
> - Pretty much anything to do with private state doesn't work anymore.

The biggest issues of trait initializers are (constructors) are:

- What order do you call them in.
- How do you pass in parameters into them.
- They would need to be called by the class constructor. Does this happen at the beginning or end?

I would argue that traits should not have initializers. It’s much easier to do something like this:

trait Trait1 {
        initTrait1() {
                // this is a regular method
                // init trait here
       }
}

class Trait1 {
        mixin Trait1;

        constructor() {
                // do work here…
                this.initTrait1()
                // do more work here...
        }
}

This kind of pattern makes initializing traits more intentional and leaves out any assumptions of what the correct order would be. And not all traits need initializers, so it leaves out a lot of complexity.

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

Re: about lightweight traits

Andrea Giammarchi-2
In reply to this post by Luke Scott
So we agree traits are not classes and notions, as well as functionality, is different. Then why would you us `class` to define a trait?

How are you going to recognize them?

I have a library that works already out of the box with traits but these are not classes, just objects that will enrich classes.

Overriding methods means having a warning in console, instead of throwing, and nothing else.
You compose whatever you want, order of defined mixins/traits matters, as well as eventual initialization of each trait.

The latter one, is available already once each instance is defined, inside the constructor.
This works to me, and I'd rather avoid the burden to walk all inheritance chain if I have to accept classes too instead of objects, but I wouldn't mind implementing it as long as I understand why that's a good thing to have in JS.

Best Regards


On Thu, Feb 12, 2015 at 9:28 PM, Luke Scott <[hidden email]> wrote:
Traits are different than classical inheritance. They simply copy functionality into a class as if the method was actually defined in the class. It isn’t inheritance. It allows you to DRY.

A real world example in my ES6 project:

- Node
- Element extends Node
- Field extends Element
- TextField extends Element
- Select extends Element, mixin Parent
- Option extends Element
- Fieldset extends Element, mixin Parent

In this case (subset of my class structure) a Fieldset has child Nodes/Elements/Fields. A Field and TextField does not have children. Yet, Select has specific child nodes. I use a trait to mixin the Parent trait to reuse functionality. Select is a parent because it has the trait, but the parent class Field is not a parent. In my case it makes no sense to re-implement that in Select, especially when having the Parent trait means something when building something like a lookup table.

I think it’s important to note that a trait knows very little of the class that implements it. For example I may mixin Parent into Select or Fieldset, but I restrict myself to methods found in Node (my base class) to be able to use the trait in any situation. If I need functionality from another trait, I mixin the other trait to make one trait.

On Feb 12, 2015, at 12:07 PM, Andrea Giammarchi <[hidden email]> wrote:

So you are saying we can just forget about extends keyword and use mixin instead for everything, right?

From: [hidden email]
Sent: ‎12/‎02/‎2015 20:05
To: [hidden email]
Cc: [hidden email]; [hidden email]
Subject: Re: about lightweight traits

Traits as class make perfect sense when you consider that classes are functions and so are traits.

On Thu, Feb 12, 2015 at 10:27 AM, Andrea Giammarchi <[hidden email]> wrote:
this thousand times ... Traits as class makes no sense to me indeed and Mark example shows plain objects passed as Trait.create ... that works just fine, except some trait initialization, which should not be a constructor, could be used too.

Is there any other language that uses same classical OOP classes as traits too? It really does not feel right to me.

Btw, reason I'm asking is because somebody else asked, I'm really OK to not rush and wait to see how it goes when it's the right time.

Best Regards

On Thu, Feb 12, 2015 at 6:32 PM, Luke Scott <[hidden email]> wrote:

On Feb 12, 2015, at 8:35 AM, Andrea Giammarchi <[hidden email]> wrote:

Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?

I find that an anty pattern.

I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.

Thoughts? Thanks!

I would agree with that. I had a trait implementation that used classes as traits, and it caused a lot of problems, especially since classes have constructors. Traits should not have constructors. I have since updated my implementation to use plain objects.


_______________________________________________
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




_______________________________________________
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: about lightweight traits

Caitlin Potter
In reply to this post by Benjamin Gruenbaum-2
>Why does ES even need traits?
>The only aspect they can help with here is the type system we don't have yet.
>
>We have `Object.assign` that works fantastically for most classic trait use cases.

They’d provide a way to explain WebIDL concepts like partial interfaces and partial dictionaries. That in itself is pretty cool. If traits were extendable and allowed providing default implementations of methods, it would also allow people to polyfill methods of partial interfaces in a much easier fashion, without having to keep track of all the various types that implement the partial interface.

That seems like a pretty good reason to make them a “thing”, to me.

> On Feb 12, 2015, at 3:08 PM, Benjamin Gruenbaum <[hidden email]> wrote:
>
> Why does ES even need traits?
> The only aspect they can help with here is the type system we don't have yet.
>
> We have `Object.assign` that works fantastically for most classic trait use cases.
>
>> On Feb 12, 2015, at 18:35, Andrea Giammarchi <[hidden email]> wrote:
>>
>> Without going down full specification/implementation details, does anyone believe that classes should/could be used, in the future, as traits/mixins too?
>>
>> I find that an anty pattern.
>>
>> I think traits should be just plain objects with an initializer or some special object flagged as trait and I'd rather leave inheritance and classes features outside this future feature.
>>
>> Thoughts? Thanks!
> _______________________________________________
> 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: about lightweight traits

Andrea Giammarchi-2
In reply to this post by Luke Scott
Luke, answering in order:

1. defining order, first come, first serve ... same as everything else on daily usage (events, Array of callbacks, etc)

2. You do not ever pass parameter to them, parameters are constructors matters, traits should be independent and unaware of constructors arguments otherwise you loose portability.
A trait should be able to work and enrich any sort of class, not just some specific one it has no notion about.

3. before everything else, since these should be stand-alone behaviors unrelated with constructors

All marked as IMO, of course :-)


On Thu, Feb 12, 2015 at 9:33 PM, Luke Scott <[hidden email]> wrote:

> On Feb 12, 2015, at 12:11 PM, Domenic Denicola <[hidden email]> wrote:
>
> From: es-discuss [mailto:[hidden email]] On Behalf Of Benjamin Gruenbaum
>
>> We have `Object.assign` that works fantastically for most classic trait use cases.
>
> Well, actually, it works extremely poorly. The old (now dead or deferred) `Object.mixin`, once called `Object.define`, is a better fit. But it still fails to account for a couple things, off the top of my head:
>
> - Being able to add custom initialization logic to the class constructor when "mixing in" a trait. You can construct a custom protocol around this, but (a) that means the class you're mixing in to needs to be aware of the protocol; (b) everyone needs to agree on a protocol across the ecosystem.
> - Pretty much anything to do with private state doesn't work anymore.

The biggest issues of trait initializers are (constructors) are:

- What order do you call them in.
- How do you pass in parameters into them.
- They would need to be called by the class constructor. Does this happen at the beginning or end?

I would argue that traits should not have initializers. It’s much easier to do something like this:

trait Trait1 {
        initTrait1() {
                // this is a regular method
                // init trait here
       }
}

class Trait1 {
        mixin Trait1;

        constructor() {
                // do work here…
                this.initTrait1()
                // do more work here...
        }
}

This kind of pattern makes initializing traits more intentional and leaves out any assumptions of what the correct order would be. And not all traits need initializers, so it leaves out a lot of complexity.

_______________________________________________
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: about lightweight traits

Andrea Giammarchi-2
Luke, forgot one detail: you do not explicitly initialize traits, these are initialized if these have an `init` or `initialize` method defined, and before the constructor is executed. So, using you example code:

```js

trait Trait1 {
        initt() {
                this.trait1Data = {what:'ever'};
       }
}

class Trait1 {
        mixin Trait1;

        constructor() {
            console.log(this.trait1Data);
            // {what:'ever'}
        }
}


```

That makes them really portable, the class is instantly aware of them since it used them as mixin, but traits are fully independent.

Do you need a lazy trait? Then you can expose an explicit method to set-it-up and invoke it whenever you want in your constructor.

Does any of this make sense? It works already in some case of mine :-)



On Thu, Feb 12, 2015 at 9:42 PM, Andrea Giammarchi <[hidden email]> wrote:
Luke, answering in order:

1. defining order, first come, first serve ... same as everything else on daily usage (events, Array of callbacks, etc)

2. You do not ever pass parameter to them, parameters are constructors matters, traits should be independent and unaware of constructors arguments otherwise you loose portability.
A trait should be able to work and enrich any sort of class, not just some specific one it has no notion about.

3. before everything else, since these should be stand-alone behaviors unrelated with constructors

All marked as IMO, of course :-)


On Thu, Feb 12, 2015 at 9:33 PM, Luke Scott <[hidden email]> wrote:

> On Feb 12, 2015, at 12:11 PM, Domenic Denicola <[hidden email]> wrote:
>
> From: es-discuss [mailto:[hidden email]] On Behalf Of Benjamin Gruenbaum
>
>> We have `Object.assign` that works fantastically for most classic trait use cases.
>
> Well, actually, it works extremely poorly. The old (now dead or deferred) `Object.mixin`, once called `Object.define`, is a better fit. But it still fails to account for a couple things, off the top of my head:
>
> - Being able to add custom initialization logic to the class constructor when "mixing in" a trait. You can construct a custom protocol around this, but (a) that means the class you're mixing in to needs to be aware of the protocol; (b) everyone needs to agree on a protocol across the ecosystem.
> - Pretty much anything to do with private state doesn't work anymore.

The biggest issues of trait initializers are (constructors) are:

- What order do you call them in.
- How do you pass in parameters into them.
- They would need to be called by the class constructor. Does this happen at the beginning or end?

I would argue that traits should not have initializers. It’s much easier to do something like this:

trait Trait1 {
        initTrait1() {
                // this is a regular method
                // init trait here
       }
}

class Trait1 {
        mixin Trait1;

        constructor() {
                // do work here…
                this.initTrait1()
                // do more work here...
        }
}

This kind of pattern makes initializing traits more intentional and leaves out any assumptions of what the correct order would be. And not all traits need initializers, so it leaves out a lot of complexity.

_______________________________________________
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: about lightweight traits

Luke Scott
I know what you’re going for, and I had this in my initial implementation. The issue then becomes:

If Trait2 mixes in Trait1, does the init method get replaced? Traits are about inserting functionality, not about inheritance. Example:

trait Trait1 {
    init() {
          // init Trait1
    }
}

trait Trait2 {
    mixin Trait1;

    init() {
        // init Trait 2
    }
}

class Foo {
    mixin Trait2;

    constructor() {
        // do Foo stuff...
    }
}

So either init is special and the call order is Trait1.init() Trait2.init() (while other methods get replaced) or Trait2.init() replaces the Trait1.init(). Also since traits are not classes, they cannot call super. You also are defying the call stack because trait initializers “just happen” internally. There is no trail to step through, unlike classes which leaves a trail of breadcrumbs with super() calls.

This version is actually easy to follow:

trait Trait1 {
    initTrait1() {
          // init Trait1
    }
}

trait Trait2 {
    mixin Trait1;

    initTrait2() {
        this.initTrait1();
        // init Trait 2
    }
}

class Foo {
    mixin Trait2;

    constructor() {
        this.initTrait2();
        // do Foo stuff...
    }
}

True, each class has to call the custom init methods. But it still addresses 95% of the problem: Adding in common functionality that doesn’t fit in classical inheritance. Also since some traits may expect to be mixed in to a subclass of a certain base, it allows you to call super before the trait initializers, and that’s something you already have to do in your local constructor, so initializing traits in the same way makes sense.

The only thing extra beyond copying implementation into a class or another trait is keeping track of what traits have been mixed in for a “hasTrait” check. This isn't necessarily required as you can easily check for a method you want to call, but it does allow you to make sure that the method belongs to trait and check once for a group of methods.

(This is my ES6 implementation of traits that I’m using now: https://gist.github.com/lukescott/36453a75c39c539f5c7d)

On Feb 12, 2015, at 12:47 PM, Andrea Giammarchi <[hidden email]> wrote:

Luke, forgot one detail: you do not explicitly initialize traits, these are initialized if these have an `init` or `initialize` method defined, and before the constructor is executed. So, using you example code:

```js

trait Trait1 {
        initt() {
                this.trait1Data = {what:'ever'};
       }
}

class Trait1 {
        mixin Trait1;

        constructor() {
            console.log(this.trait1Data);
            // {what:'ever'}
        }
}


```

That makes them really portable, the class is instantly aware of them since it used them as mixin, but traits are fully independent.

Do you need a lazy trait? Then you can expose an explicit method to set-it-up and invoke it whenever you want in your constructor.

Does any of this make sense? It works already in some case of mine :-)



On Thu, Feb 12, 2015 at 9:42 PM, Andrea Giammarchi <[hidden email]> wrote:
Luke, answering in order:

1. defining order, first come, first serve ... same as everything else on daily usage (events, Array of callbacks, etc)

2. You do not ever pass parameter to them, parameters are constructors matters, traits should be independent and unaware of constructors arguments otherwise you loose portability.
A trait should be able to work and enrich any sort of class, not just some specific one it has no notion about.

3. before everything else, since these should be stand-alone behaviors unrelated with constructors

All marked as IMO, of course :-)


On Thu, Feb 12, 2015 at 9:33 PM, Luke Scott <[hidden email]> wrote:

> On Feb 12, 2015, at 12:11 PM, Domenic Denicola <[hidden email]> wrote:
>
> From: es-discuss [mailto:[hidden email]] On Behalf Of Benjamin Gruenbaum
>
>> We have `Object.assign` that works fantastically for most classic trait use cases.
>
> Well, actually, it works extremely poorly. The old (now dead or deferred) `Object.mixin`, once called `Object.define`, is a better fit. But it still fails to account for a couple things, off the top of my head:
>
> - Being able to add custom initialization logic to the class constructor when "mixing in" a trait. You can construct a custom protocol around this, but (a) that means the class you're mixing in to needs to be aware of the protocol; (b) everyone needs to agree on a protocol across the ecosystem.
> - Pretty much anything to do with private state doesn't work anymore.

The biggest issues of trait initializers are (constructors) are:

- What order do you call them in.
- How do you pass in parameters into them.
- They would need to be called by the class constructor. Does this happen at the beginning or end?

I would argue that traits should not have initializers. It’s much easier to do something like this:

trait Trait1 {
        initTrait1() {
                // this is a regular method
                // init trait here
       }
}

class Trait1 {
        mixin Trait1;

        constructor() {
                // do work here…
                this.initTrait1()
                // do more work here...
        }
}

This kind of pattern makes initializing traits more intentional and leaves out any assumptions of what the correct order would be. And not all traits need initializers, so it leaves out a lot of complexity.

_______________________________________________
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: about lightweight traits

Peter Seliger
In reply to this post by Andrea Giammarchi-2
As for JavaScript, I strongly believe, Role based composition patterns
like Mixins or Traits should be function based.

Whereas the widely used purely object based approach (together with
some copy mechanics provided by one of the several [extends]
implementations) does still work for Mixins, it is going to fail with Traits.

Traits have to provide/implement functionality for conflict resolution of
methods, for requiring and for excluding them. For JavaScript this can
be achieved easily by just making use of the module pattern and another
function based mixin, that does provide those mentioned composition
methods.

Function based Mixins/Traits have to be applied by [call] or [apply] only.

I always strongly will argue that a function based approach is most
natural for this languages design since it does provide delegation for
free and at the same time also enables injecting of and passing around
additional state for both Mixins and Traits which is another appealing
feature one gets for free too with using [call] or [apply].

And answering the OP's question; Role based composition in JavaScript
should work on both levels instance/object level and class level. For this
reason alone one should not go for using "Classes" as Mixins.

Maybe future language specifications should only describe the syntactic
sugar, that shadows/encapsulates the usage of function based Mixins/
Traits as described e.g. with [1].


[1] The linked article should not be considered spam or selfish - I'm the
author of it. Maybe it helps clarifying my point of view, since it is a brief
deep dive into the matter of Roles, Mixins, Traits, Talents within the context
of JavaScript -
[http://peterseliger.blogspot.de/2014/04/the-many-talents-of-javascript.html#the-many-talents-of-javascript-for-generalizing-role-oriented-programming-approaches-like-traits-and-mixins].


Thanks - Peter



On Thu, Feb 12, 2015 at 5:35 PM, Andrea Giammarchi
<[hidden email]> wrote:

> Without going down full specification/implementation details, does anyone
> believe that classes should/could be used, in the future, as traits/mixins
> too?
>
> I find that an anty pattern.
>
> I think traits should be just plain objects with an initializer or some
> special object flagged as trait and I'd rather leave inheritance and classes
> features outside this future feature.
>
> Thoughts? Thanks!
>
> _______________________________________________
> 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
12