[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: RubyTraits 0.1

Yukihiro Matsumoto

10/15/2007 3:38:00 PM

Hi,

In message "Re: RubyTraits 0.1"
on Tue, 16 Oct 2007 00:23:43 +0900, Trans <transfire@gmail.com> writes:

|I see. So you don't really like the fact that modules fit into the
|inheritance chain? That's interesting.

Actually they both have their own good. I like them both. I dislike
to have them both in a language. Traits injection is clear and less
error prone (there's no possibility of conflicts), but sometimes
method overriding is _very_ useful, where aliasing is very poor way to
create method combination.

If someone come to the idea to allow modules to have merits from both
mixins and traits at once (without demerit), I'd love to hear.

matz.

10 Answers

Robert Dober

10/15/2007 3:50:00 PM

0

On 10/15/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:
> Hi,
>
> In message "Re: RubyTraits 0.1"
> on Tue, 16 Oct 2007 00:23:43 +0900, Trans <transfire@gmail.com> writes:
>
> |I see. So you don't really like the fact that modules fit into the
> |inheritance chain? That's interesting.
>
> Actually they both have their own good. I like them both. I dislike
> to have them both in a language. Traits injection is clear and less
> error prone (there's no possibility of conflicts), but sometimes
> method overriding is _very_ useful, where aliasing is very poor way to
> create method combination.
Actually Traits allow both
when you compose traits conflicts will be created
when you use traits (that is when you inject the methods) they can
perfectly be overridden.

Example
t1 = trait { def a; 42 end }
t2 = trait { def a; 46 end }
t3 = t1 + t2
class A
use t3
end
A.new.a --> Conflict
but
class A
use t1 # or t3 for that matter ### flattening is going on here
def a; 22 end
end
A.new.a --> 22
according to Schaerli's paper you can even do
t4 = trait { use t1; def a; 222 end }
no conflicts here

The flattening property of traits will however hide the trait from the
inheritance chain, behavior is composed not inherited that is an
important trait of traits - forgive the pun ;).
>
> If someone come to the idea to allow modules to have merits from both
> mixins and traits at once (without demerit), I'd love to hear.
Hmm, I almost fail to see what merit modules have that traits do not have?
That you can say isa? for an instance of a class that had a module mixed in?
Maybe, no idea if this is worth it.

Cheers
Robert

--
what do I think about Ruby?
http://ruby-smalltalk.blo...

Daniel Berger

10/15/2007 4:49:00 PM

0



On Oct 15, 9:38 am, Yukihiro Matsumoto <m...@ruby-lang.org> wrote:
> Hi,
>
> In message "Re: RubyTraits 0.1"
> on Tue, 16 Oct 2007 00:23:43 +0900, Trans <transf...@gmail.com> writes:
>
> |I see. So you don't really like the fact that modules fit into the
> |inheritance chain? That's interesting.
>
> Actually they both have their own good. I like them both. I dislike
> to have them both in a language. Traits injection is clear and less
> error prone (there's no possibility of conflicts), but sometimes
> method overriding is _very_ useful, where aliasing is very poor way to
> create method combination.
>
> If someone come to the idea to allow modules to have merits from both
> mixins and traits at once (without demerit), I'd love to hear.

I solved this "problem" over two years ago with fine grained mixins.
Please see http://rubyforge.org/docman/view.php/735/309/R...
and look at the synopsis. Ideas (and code) in that library also came
from Ara Howard and Mauricio Fernandez.

I don't want up front object composition. To me that's like static
typing, except for object composition. At worst, a warning should be
issued if a double inclusion occurs. This is what the 'use' library
does in verbose mode.

Regards,

Dan


Trans

10/15/2007 5:49:00 PM

0

This is an interesting discussion --what qualifies as "traits".

On Oct 15, 8:50 am, "Robert Dober" <robert.do...@gmail.com> wrote:

> Actually Traits allow both
> when you compose traits conflicts will be created
> when you use traits (that is when you inject the methods) they can
> perfectly be overridden.
>
> Example
> t1 = trait { def a; 42 end }
> t2 = trait { def a; 46 end }
> t3 = t1 + t2
> class A
> use t3
> end
> A.new.a --> Conflict
> but
> class A
> use t1 # or t3 for that matter ### flattening is going on here
> def a; 22 end
> end
> A.new.a --> 22
> according to Schaerli's paper you can even do
> t4 = trait { use t1; def a; 222 end }
> no conflicts here

Interesting. But why not have a default definition based on
combination order instead of raising a Conflict? One can always
override/redefine. But having a conflict forces one to redefine, which
seems more limiting to me. But maybe I missing something, I haven't
read the paper (link?).

> The flattening property of traits will however hide the trait from the
> inheritance chain, behavior is composed not inherited that is an
> important trait of traits - forgive the pun ;).

Is it an absolutely necessary trait, though? The theory defines
flattening b/c it is offering an alternate means of composition.
However, we have module chains at our disposal. Can we not take
advantage of them in our implementation and still be considered
"traits"? Might we not view Ruby's linearization of the inheritance
chain as an effective means of "flattening", whether it is or not in
the strictest sense? Or are there some other important reasons for
flattening (especially one that Ruby's module chains can't emulate)?

> > If someone come to the idea to allow modules to have merits from both
> > mixins and traits at once (without demerit), I'd love to hear.
>
> Hmm, I almost fail to see what merit modules have that traits do not have?
> That you can say isa? for an instance of a class that had a module mixed in?
> Maybe, no idea if this is worth it.

That's one reason. But more importantly, calling super, ie. method
inheritance. Does the formal design of traits have super?

T.


Trans

10/15/2007 8:34:00 PM

0



On Oct 15, 9:49 am, Daniel Berger <djber...@gmail.com> wrote:
> On Oct 15, 9:38 am, Yukihiro Matsumoto <m...@ruby-lang.org> wrote:
>
>
>
> > Hi,
>
> > In message "Re: RubyTraits 0.1"
> > on Tue, 16 Oct 2007 00:23:43 +0900, Trans <transf...@gmail.com> writes:
>
> > |I see. So you don't really like the fact that modules fit into the
> > |inheritance chain? That's interesting.
>
> > Actually they both have their own good. I like them both. I dislike
> > to have them both in a language. Traits injection is clear and less
> > error prone (there's no possibility of conflicts), but sometimes
> > method overriding is _very_ useful, where aliasing is very poor way to
> > create method combination.
>
> > If someone come to the idea to allow modules to have merits from both
> > mixins and traits at once (without demerit), I'd love to hear.
>
> I solved this "problem" over two years ago with fine grained mixins.
> Please seehttp://rubyforge.org/docman/view.php/735/309/R...
> and look at the synopsis. Ideas (and code) in that library also came
> from Ara Howard and Mauricio Fernandez.
>
> I don't want up front object composition. To me that's like static
> typing, except for object composition. At worst, a warning should be
> issued if a double inclusion occurs. This is what the 'use' library
> does in verbose mode.

Kind of like #integrate.

# Using integrate is just like using include except the
# module included is a reconstruction of the one given
# altered by the commands given in the block.
#
# Convenient commands available are: #rename, #redef,
# #remove, #nodef and #wrap. But any module method
# can be used.
#
# module W
# def q ; "q" ; end
# def y ; "y" ; end
# end
#
# class X
# integrate W do
# nodef :y
# end
# end
#
# x = X.new
# x.q #=> "q"
# x.y #=> NoMethodError
#
# This is like #revisal, but #revisal only
# returns the reconstructred module. It does not
# include it.

The significant difference between this and your #use method is that
#use can more easily add a small select group of methods from a module
--I think that's that gist of your lib. However, if you find yourself
"cherry picking" methods from a module like that, it's time to rethink
the design. Plus, implementation of that is terribly inefficient
(having to remove all other methods).

At any rate, Traits are much prettier:

class X
include W - :y
end

T.


Daniel Berger

10/15/2007 9:58:00 PM

0



On Oct 15, 2:33 pm, Trans <transf...@gmail.com> wrote:

<snip>

> The significant difference between this and your #use method is that
> #use can more easily add a small select group of methods from a module
> --I think that's that gist of your lib. However, if you find yourself
> "cherry picking" methods from a module like that, it's time to rethink
> the design. Plus, implementation of that is terribly inefficient
> (having to remove all other methods).
>
> At any rate, Traits are much prettier:
>
> class X
> include W - :y
> end

I think excluding specific methods would be unusual in practice. Of
course, I'm of the opinion that traits are a solution in search of a
problem to begin with, so take my opinions with a grain of salt.

Anyway, I suppose I could add an option where it simply discards dup's
dynamically when a module is included:

class X
use ModA, :no_override
end

That would be interpreted as "include all methods unless already
defined".

Regards,

Dan


Robert Dober

10/16/2007 9:34:00 AM

0

On 10/15/07, Trans <transfire@gmail.com> wrote:
<snip> >
> > Hmm, I almost fail to see what merit modules have that traits do not have?
> > That you can say isa? for an instance of a class that had a module mixed in?
> > Maybe, no idea if this is worth it.
>
> That's one reason. But more importantly, calling super, ie. method
> inheritance. Does the formal design of traits have super?
Yup it is one of the cornerstones of the definition, super is resolved
dynamically
in the inheritance chain.
R

--
what do I think about Ruby?
http://ruby-smalltalk.blo...

Robert Dober

10/16/2007 9:44:00 AM

0

On 10/15/07, Daniel Berger <djberg96@gmail.com> wrote:
>
>
> On Oct 15, 9:38 am, Yukihiro Matsumoto <m...@ruby-lang.org> wrote:
> > Hi,
> >
> > In message "Re: RubyTraits 0.1"
> > on Tue, 16 Oct 2007 00:23:43 +0900, Trans <transf...@gmail.com> writes:
> >
> > |I see. So you don't really like the fact that modules fit into the
> > |inheritance chain? That's interesting.
> >
> > Actually they both have their own good. I like them both. I dislike
> > to have them both in a language. Traits injection is clear and less
> > error prone (there's no possibility of conflicts), but sometimes
> > method overriding is _very_ useful, where aliasing is very poor way to
> > create method combination.
> >
> > If someone come to the idea to allow modules to have merits from both
> > mixins and traits at once (without demerit), I'd love to hear.
>
> I solved this "problem" over two years ago with fine grained mixins.
> Please see http://rubyforge.org/docman/view.php/735/309/R...
> and look at the synopsis. Ideas (and code) in that library also came
> from Ara Howard and Mauricio Fernandez.
>
> I don't want up front object composition. To me that's like static
> typing, except for object composition. At worst, a warning should be
> issued if a double inclusion occurs. This is what the 'use' library
> does in verbose mode.
If what you did solves your problem than that is good, it however does
not address the issues that are adressed by traits.
And the good thing about traits is that, if you do not want to use
them, then just do not.
I have followed the discussion on the Squeak Mailing List before
making traits part of the kernel. The killer argument was, ok we are
going to do this because it will make the code base "better" but
nobody will ever need to care about Traits unless they want.
To be fair, Squeak needed Traits much more than Ruby as they had no Mixins.
OTOH I have never heard anybody complain that traits remind them of
static typing, would you mind to elaborate on that Daniel?

Cheers
Robert

--
what do I think about Ruby?
http://ruby-smalltalk.blo...

Daniel Berger

10/16/2007 11:02:00 AM

0

Robert Dober wrote:
> On 10/15/07, Daniel Berger <djberg96@gmail.com> wrote:
>>
>> On Oct 15, 9:38 am, Yukihiro Matsumoto <m...@ruby-lang.org> wrote:
>>> Hi,
>>>
>>> In message "Re: RubyTraits 0.1"
>>> on Tue, 16 Oct 2007 00:23:43 +0900, Trans <transf...@gmail.com> writes:
>>>
>>> |I see. So you don't really like the fact that modules fit into the
>>> |inheritance chain? That's interesting.
>>>
>>> Actually they both have their own good. I like them both. I dislike
>>> to have them both in a language. Traits injection is clear and less
>>> error prone (there's no possibility of conflicts), but sometimes
>>> method overriding is _very_ useful, where aliasing is very poor way to
>>> create method combination.
>>>
>>> If someone come to the idea to allow modules to have merits from both
>>> mixins and traits at once (without demerit), I'd love to hear.
>> I solved this "problem" over two years ago with fine grained mixins.
>> Please see http://rubyforge.org/docman/view.php/735/309/R...
>> and look at the synopsis. Ideas (and code) in that library also came
>> from Ara Howard and Mauricio Fernandez.
>>
>> I don't want up front object composition. To me that's like static
>> typing, except for object composition. At worst, a warning should be
>> issued if a double inclusion occurs. This is what the 'use' library
>> does in verbose mode.
> If what you did solves your problem than that is good, it however does
> not address the issues that are adressed by traits.

The multi-mixin (i.e. total ordering) problem is one of the primary
reasons for Traits, or at least, one of the main digs against mixin
inheritence. My library solves that in a dynamic, but not strict, manner.

> And the good thing about traits is that, if you do not want to use
> them, then just do not.

As a third party library they're fine. But core? No.

> I have followed the discussion on the Squeak Mailing List before
> making traits part of the kernel. The killer argument was, ok we are
> going to do this because it will make the code base "better" but
> nobody will ever need to care about Traits unless they want.
> To be fair, Squeak needed Traits much more than Ruby as they had no Mixins.

Exactly. In languages that have no mixins I think Traits are fine and,
from what I can gather, it's the mixin capability those languages and
communities are really after, not the composition.

> OTOH I have never heard anybody complain that traits remind them of
> static typing, would you mind to elaborate on that Daniel?

In a couple of ways. First, raising an error if method conflicts arise
feels too strict for a dynamic language. I'd like a warning, but nothing
more. Also, a trait requires a set of methods that serve as parameters
for the provided behavior. Like static typing, that means up-front
declarations that don't mesh well with the overall philosophy of dynamic
languages IMO.

Regards,

Dan

Robert Dober

10/16/2007 12:05:00 PM

0

On 10/16/07, Daniel Berger <djberg96@gmail.com> wrote:
> Robert Dober wrote:
> > On 10/15/07, Daniel Berger <djberg96@gmail.com> wrote:
> >>
> >> On Oct 15, 9:38 am, Yukihiro Matsumoto <m...@ruby-lang.org> wrote:
> >>> Hi,
> >>>
> >>> In message "Re: RubyTraits 0.1"
> >>> on Tue, 16 Oct 2007 00:23:43 +0900, Trans <transf...@gmail.com> writes:
> >>>
> >>> |I see. So you don't really like the fact that modules fit into the
> >>> |inheritance chain? That's interesting.
> >>>
> >>> Actually they both have their own good. I like them both. I dislike
> >>> to have them both in a language. Traits injection is clear and less
> >>> error prone (there's no possibility of conflicts), but sometimes
> >>> method overriding is _very_ useful, where aliasing is very poor way to
> >>> create method combination.
> >>>
> >>> If someone come to the idea to allow modules to have merits from both
> >>> mixins and traits at once (without demerit), I'd love to hear.
> >> I solved this "problem" over two years ago with fine grained mixins.
> >> Please see http://rubyforge.org/docman/view.php/735/309/R...
> >> and look at the synopsis. Ideas (and code) in that library also came
> >> from Ara Howard and Mauricio Fernandez.
> >>
> >> I don't want up front object composition. To me that's like static
> >> typing, except for object composition. At worst, a warning should be
> >> issued if a double inclusion occurs. This is what the 'use' library
> >> does in verbose mode.
> > If what you did solves your problem than that is good, it however does
> > not address the issues that are adressed by traits.
>
> The multi-mixin (i.e. total ordering) problem is one of the primary
> reasons for Traits, or at least, one of the main digs against mixin
> inheritence. My library solves that in a dynamic, but not strict, manner.
>
> > And the good thing about traits is that, if you do not want to use
> > them, then just do not.
>
> As a third party library they're fine. But core? No.
I was not thinking of making it core, and Matz said too that having
Mixins already he will refrain from putting them into core, I feel
that this is a reasonable choice, no hard feelings at all.
>
<snip>
> > OTOH I have never heard anybody complain that traits remind them of
> > static typing, would you mind to elaborate on that Daniel?
>
> In a couple of ways. First, raising an error if method conflicts arise
> feels too strict for a dynamic language. I'd like a warning, but nothing
> more. Also, a trait requires a set of methods that serve as parameters
> for the provided behavior. Like static typing, that means up-front
> declarations that don't mesh well with the overall philosophy of dynamic
> languages IMO.
Hmm honestly I think that your conclusion is correct but your premises are not.
Traits are as dynamical as modules if you just "use" them, the conflict handling
is an extra you get from combining them.
In the semantics of my traits package that would be
class A
use t1, t2 # conflicts might be defined as this is equivalent to
# use t1+t2 which is equivalent to use t2 + t1 per definition
end

class A
use t1
use t2
end

does almost exactly what you would have with modules only that use t2
will always take effect because of the flattening property.

Forgive me if I am too religious about this, but I feel that traits
are an exciting thing :).

But there is one thing which is "wrong" with my package if you are
going to dynamically extend traits they will break, but that is the
fault of my - simple - implementation not really the fault of traits
:(, it might even be fixable.

Thx for your time.

Cheers
Robert


--
what do I think about Ruby?
http://ruby-smalltalk.blo...

Trans

10/16/2007 7:44:00 PM

0



On Oct 15, 8:38 am, Yukihiro Matsumoto <m...@ruby-lang.org> wrote:
> Hi,
>
> In message "Re: RubyTraits 0.1"
> on Tue, 16 Oct 2007 00:23:43 +0900, Trans <transf...@gmail.com> writes:
>
> |I see. So you don't really like the fact that modules fit into the
> |inheritance chain? That's interesting.
>
> Actually they both have their own good. I like them both. I dislike
> to have them both in a language. Traits injection is clear and less
> error prone (there's no possibility of conflicts), but sometimes
> method overriding is _very_ useful, where aliasing is very poor way to
> create method combination.
>
> If someone come to the idea to allow modules to have merits from both
> mixins and traits at once (without demerit), I'd love to hear.

I couldn't help but think about what a solution to that might look
like --it would have to have the layerability of modules but the
simplicity of traits. To do that, I think methods would have to be
more independent. Instead of a Method being a single function
belonging to class (or module/trait) it would be a linked-list of
them. Each of these would have a second link tying it to the trait/
module. Eg.

.-> Class1
| .-> TraitX .-> TraitY
.-------- | |
| -> foo_method-> foo_method -> foo_method
'--------

It would also be possible to do around advice very easily too, because
a method could be added to the chain that's not tied to a Triat/
Module.

.-> Class1
| .-> TraitX .-> TraitY
.-------- | |
| -> foo_method -> foo_method -> foo_method -> foo_method
'--------

#super would be dynamically resolved by following the link.

I think this could provide the advantages of both traits and modules
in a single system.

T.