Quelques propos (récents) de matz (Yukihiro Matsumoto) à propos des Traits :
- "Too bad I didn't know about traits when I designed Ruby."
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/274227
- "If I knew traits before designing Ruby, I'd have chosen traits over
modules. But that's the life."
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/274242
this is why I will try to find some times to polish traits in squeak
stef
Out of curiosity, what is the difference between Ruby's modules and traits? They strike me as extremely similar, but not being the local Ruby guru I might overlook some implications. As far as I understand it both allow "grouping of methods" (aka: include statements) and both disallow state (in Ruby's case simply because state access is always a dynamic attribute lookup). So what's the difference?
Cheers, - Andreas
stephane ducasse wrote:
Quelques propos (récents) de matz (Yukihiro Matsumoto) à propos des Traits :
- "Too bad I didn't know about traits when I designed Ruby."
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/274227
- "If I knew traits before designing Ruby, I'd have chosen traits over
modules. But that's the life."
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/274242
this is why I will try to find some times to polish traits in squeak
stef
-----Original Message----- From: squeak-dev-bounces@lists.squeakfoundation.org [mailto:squeak-dev-bounces@lists.squeakfoundation.org] On Behalf Of Andreas Raab Sent: Monday, October 22, 2007 1:37 PM To: The general-purpose Squeak developers list Subject: Re: Fwd: [Squeak-fr] Ruby et les Traits.
Out of curiosity, what is the difference between Ruby's modules and traits? They strike me as extremely similar, but not being the local Ruby guru I might overlook some implications. As far as I understand it both allow "grouping of methods" (aka: include statements) and both disallow state (in Ruby's case simply because state access is always a dynamic attribute lookup). So what's the difference?
Cheers,
- Andreas
Traits can be composed better because you can specify which methods you want from conflicting traits explicitly. Ruby's modules I believe don't allow you to mix and match, but is based on inclusion order only. Other than that, I think they're the same.
Ramon Leon http://onsmalltalk.com
Ramon Leon wrote:
Traits can be composed better because you can specify which methods you want from conflicting traits explicitly. Ruby's modules I believe don't allow you to mix and match, but is based on inclusion order only.
Do you have an example for this? I'm uncertain what a "conflicting trait" is and how this would be resolved (in either implementation).
Cheers, - Andreas
-----Original Message----- From: squeak-dev-bounces@lists.squeakfoundation.org [mailto:squeak-dev-bounces@lists.squeakfoundation.org] On Behalf Of Andreas Raab Sent: Monday, October 22, 2007 2:04 PM To: The general-purpose Squeak developers list Subject: Re: Fwd: [Squeak-fr] Ruby et les Traits.
Ramon Leon wrote:
Traits can be composed better because you can specify which methods you want from conflicting traits explicitly. Ruby's
modules I believe
don't allow you to mix and match, but is based on inclusion
order only.
Do you have an example for this? I'm uncertain what a "conflicting trait" is and how this would be resolved (in either implementation).
Cheers,
- Andreas
Well, should two traits both have methods of the same name, Traits lets you pick and choose which one you want..
Object subclass: #CustomHero uses: SupermanTrait - {#run. #fly. #think} + FlashTrait - {#heal. #think} + BatmanTrait -{#heal. #run} instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'SomeCategory'
So you can manually mix and match Traits to get the desired implementation, in this case a Hero that's like Superman but can't fly, is still invulnerable, runs as fast as the Flash and is as smart as Batman. Or you want to compose a new Trait by mixing and matching methods from several other traits.
More realistically say you have an Enumerable Trait that only requires you implement #do: in your class... You may not want to provide everything the module provides, so you selectively remove #select:, #detect: while allowing the rest.
Ruby's modules don't allow this level of control. Given modules with conflicting methods, you either get all from one or all from the other depending on the order you include them. That is my understanding anyway.
Ramon Leon http://onsmalltalk.com
On Oct 22, 2007, at 2:44 PM, Ramon Leon wrote:
Ruby's modules don't allow this level of control. Given modules with conflicting methods, you either get all from one or all from the other depending on the order you include them. That is my understanding anyway.
Ramon is basically correct - the difference is in the way the conflicts are resolved. If a method is defined in more than one place, which one is used?
Ruby's modules work by inserting the module into the superclass chain. The order that modules are included is the order they're inserted, so by including module later in the sequence you can override earlier modules the same way a subclass can override a superclass. For example, the following script prints "a A":
module Uppercase def alpha 'A' end end
module Lowercase def alpha 'a' end end
class Upperfirst include Uppercase include Lowercase end
class Uppersecond include Lowercase include Uppercase end
first = Upperfirst.new second = Uppersecond.new
puts "#{first.alpha} #{second.alpha}"
Traits, on the other hand works by adding the methods directly into the class's method dictionary. It can't rely on inheritance to resolve conflicts, so it provides ways of explicitly resolving conflicts, as Ramon explained.
Colin
But since these two systems are so similar what places are modules used in Ruby to the best effect? I always used Haskell as my comparison, but it turns out this isn't a good idea because Haskell isn't an OO language, so the applicability is different.
In my conversations with Andreas, I always used Magnitude as the prime "obvious use case" example for Traits, but that turns out this actually doesn't work very well for the reasons laid out here: http://lists.squeakfoundation.org/pipermail/squeak-dev/2007-September/120256...
Stephane, you might consider the things in that mail when you write the tools, i.e. make some tools with the idea that making objects can consist largely of dropping traits or even trait composition "templates" onto a class to define it.
Andreas, you mentioned a lot of extra complexity created by Traits (in Proto and so). Is this due to the implementation of Traits themselves or a place where someone tried to show "value" with some refactorings that made things worse?
If it is the latter, then I had a plan of removing these refactoring and restarting with the goals defined in the email above. My plate is full and overflowing, but I could farm this task out.
On 10/23/07, Colin Putney cputney@wiresong.ca wrote:
On Oct 22, 2007, at 2:44 PM, Ramon Leon wrote:
Ruby's modules don't allow this level of control. Given modules with
conflicting methods, you either get all from one or all from the other
depending on the order you include them. That is my understanding anyway. Ramon is basically correct - the difference is in the way the conflicts are resolved. If a method is defined in more than one place, which one is used?
Ruby's modules work by inserting the module into the superclass chain. The order that modules are included is the order they're inserted, so by including module later in the sequence you can override earlier modules the same way a subclass can override a superclass. For example, the following script prints "a A":
module Uppercase def alpha 'A' end end
module Lowercase def alpha 'a' end end
class Upperfirst include Uppercase include Lowercase end
class Uppersecond include Lowercase include Uppercase end
first = Upperfirst.new second = Uppersecond.new
puts "#{first.alpha} #{second.alpha}"
Traits, on the other hand works by adding the methods directly into the class's method dictionary. It can't rely on inheritance to resolve conflicts, so it provides ways of explicitly resolving conflicts, as Ramon explained.
Colin
Il giorno mar, 23/10/2007 alle 07.02 +0200, Jason Johnson ha scritto:
But since these two systems are so similar what places are modules used in Ruby to the best effect? I always used Haskell as my comparison, but it turns out this isn't a good idea because Haskell isn't an OO language, so the applicability is different.
An example of module use in the Ruby standard library is the collections system. Ruby doesn't have an abstract Collection class that acts as the superclass for all collection classes, but it has an Enumerable module that implements methods such as #select, #collect, #inject, etc. All these methods depend on the including class implementing #each (#each is the Ruby equivalent of #do: ). All the concrete collection classes have an #each method and include Enumerable in order to support the complete collection protocol.
Giovanni
thanks for the pointer! I should look at that.
Stef
On 23 oct. 07, at 10:01, Giovanni Corriga wrote:
Il giorno mar, 23/10/2007 alle 07.02 +0200, Jason Johnson ha scritto:
But since these two systems are so similar what places are modules used in Ruby to the best effect? I always used Haskell as my comparison, but it turns out this isn't a good idea because Haskell isn't an OO language, so the applicability is different.
An example of module use in the Ruby standard library is the collections system. Ruby doesn't have an abstract Collection class that acts as the superclass for all collection classes, but it has an Enumerable module that implements methods such as #select, #collect, #inject, etc. All these methods depend on the including class implementing #each (#each is the Ruby equivalent of #do: ). All the concrete collection classes have an #each method and include Enumerable in order to support the complete collection protocol.
Giovanni
Hi jason
I'm not connected (just in a slooooow train lost in the country side of the Alps)
In my conversations with Andreas, I always used Magnitude as the prime "obvious use case" example for Traits, but that turns out this actually doesn't work very well for the reasons laid out here: http://lists.squeakfoundation.org/pipermail/squeak-dev/2007- September/120256.html
Stephane, you might consider the things in that mail when you write the tools, i.e. make some tools with the idea that making objects can consist largely of dropping traits or even trait composition "templates" onto a class to define it.
Yes this would be interesting.
Andreas, you mentioned a lot of extra complexity created by Traits (in Proto and so). Is this due to the implementation of Traits themselves or a place where someone tried to show "value" with some refactorings that made things worse?
I think that the kernel is not worse (but tools are lacking to navigate). This is due to: - the fact that we could not change totally the class (for example you cannot change Behavior). - the tools does not help navigating the code (this is difficult to introduce another navigation axe). - this was difficult to identify traits in existing code (because sometimes the code is not that nicely organized).
I think that Nile is a good example of using traits (after we can discuss if ReadWriteStream and ReadStream suck or not) Traits are like first class protocol that can be shared and we do not get a nice way to navigate them.
If it is the latter, then I had a plan of removing these refactoring and restarting with the goals defined in the email above. My plate is full and overflowing, but I could farm this task out.
Have a look at Nile and comment it. I would like to redo the same with the collections. restarting test first from scratch.
Stef
On 10/23/07, Colin Putney cputney@wiresong.ca wrote:
On Oct 22, 2007, at 2:44 PM, Ramon Leon wrote:
Ruby's modules don't allow this level of control. Given modules with
conflicting methods, you either get all from one or all from the other
depending on the order you include them. That is my understanding anyway. Ramon is basically correct - the difference is in the way the conflicts are resolved. If a method is defined in more than one place, which one is used?
Ruby's modules work by inserting the module into the superclass chain. The order that modules are included is the order they're inserted, so by including module later in the sequence you can override earlier modules the same way a subclass can override a superclass. For example, the following script prints "a A":
module Uppercase def alpha 'A' end end
module Lowercase def alpha 'a' end end
class Upperfirst include Uppercase include Lowercase end
class Uppersecond include Lowercase include Uppercase end
first = Upperfirst.new second = Uppersecond.new
puts "#{first.alpha} #{second.alpha}"
Traits, on the other hand works by adding the methods directly into the class's method dictionary. It can't rely on inheritance to resolve conflicts, so it provides ways of explicitly resolving conflicts, as Ramon explained.
Colin
Traits, on the other hand works by adding the methods directly into the class's method dictionary. It can't rely on inheritance to resolve conflicts, so it provides ways of explicitly resolving conflicts, as Ramon explained.
The way conflicts are resolved in not an accident in traits but a decision to give to the composer the control. This is why we did not wanted linearisation as an implicit way to solve conflicts (I programmed with mixin in CLOS during my PhD and there it was also linearisation based).
Stef
sorry I'm travelling. The key difference between mixin like approaches and traits is that with traits the composer is in control. There is an automatic conflict resolution but it is explicit in traits. With mixin the linearisation is implicit and often out of control. For state we choose that to avoid merging of attributes having the same names, but this is not essential.
Some thoughts about our recent research: We worked on stateful traits but I do not like what we did. I would like to revisit that soon with something much simpler. Roel is presenting freezable traits (to control early bindness of methods), but the semantics is too complex may be a ruby one is better.After done all that I realized that freezable traits is far too complex. So we learned something: traits version 1 are cool. Traits have alias (to give a different name to a method) but may be deep renaming (as in Eiffel) would be better (but implementation would be more complex).
Stef
On 22 oct. 07, at 22:37, Andreas Raab wrote:
Out of curiosity, what is the difference between Ruby's modules and traits? They strike me as extremely similar, but not being the local Ruby guru I might overlook some implications. As far as I understand it both allow "grouping of methods" (aka: include statements) and both disallow state (in Ruby's case simply because state access is always a dynamic attribute lookup). So what's the difference?
Cheers,
- Andreas
stephane ducasse wrote:
Quelques propos (récents) de matz (Yukihiro Matsumoto) à propos des Traits :
- "Too bad I didn't know about traits when I designed Ruby."
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/274227
- "If I knew traits before designing Ruby, I'd have chosen traits
over modules. But that's the life."
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/274242
this is why I will try to find some times to polish traits in squeak stef
Hi Andreas,
Ruby modules are mixins. The only way to compose mixins is inheritance. With traits, you have different operators to do some fine tuning.
Cheers, Alexandre
On 22 Oct 2007, at 16:37, Andreas Raab wrote:
Out of curiosity, what is the difference between Ruby's modules and traits? They strike me as extremely similar, but not being the local Ruby guru I might overlook some implications. As far as I understand it both allow "grouping of methods" (aka: include statements) and both disallow state (in Ruby's case simply because state access is always a dynamic attribute lookup). So what's the difference?
Cheers,
- Andreas
stephane ducasse wrote:
Quelques propos (récents) de matz (Yukihiro Matsumoto) à propos des Traits :
- "Too bad I didn't know about traits when I designed Ruby."
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/274227
- "If I knew traits before designing Ruby, I'd have chosen traits
over modules. But that's the life."
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/274242
this is why I will try to find some times to polish traits in squeak stef
squeak-dev@lists.squeakfoundation.org