RubyTraits 0.1

On Oct 15, 3:24 pm, Jay L. [email protected] wrote:

If I cross my eyes, they still look the same, but I also see a 3D Ferris
wheel pop out.

Uhm. Yeah. Oops. :slight_smile:

I had meant to type:

Although this syntax reads well:
include ModA, :exclude => :foo
I think this particular syntax appears odd:
include ModA, :include => :foo
where this is better:
use ModA, :include => :foo
ā€¦but apparently got lazy. Sorry 'bout that.

Have fun at the 3D circus. :slight_smile:

On Mon, 15 Oct 2007 13:13:40 -0700, Phrogz wrote:

Although this syntax reads well:
include ModA, :exclude => :foo
I think this particular syntax appears odd:
include ModA, :include => :foo
where this is better:
include ModA, :include => :foo

Iā€™m staring and staring and staring, but #2 still looks the same as #3.

If I cross my eyes, they still look the same, but I also see a 3D Ferris
wheel pop out.

On Oct 15, 3:35 pm, Phrogz [email protected] wrote:

Iā€™m staring and staring and staring, but #2 still looks the same as #3.
where this is better:
use ModA, :include => :foo

ā€¦but apparently got lazy. Sorry 'bout that.

The :include option is the default if no keywords are supplied. So,
you can do this:

use ModA, :foo

If we override ā€˜includeā€™, then itā€™s just this:

include ModA, :foo

Regards,

Dan

On Oct 15, 2:33 pm, Trans [email protected] wrote:

  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

On Oct 15, 2:15 pm, Phrogz [email protected] wrote:

and ā€˜meth_bā€™
use Mod_B, :exclude => :meth_c # same net result as
above
end

Shouldnā€™t that be :exclude => :meth_a instead, to get the same net
result?

It should be ā€œ:include => [:meth_a, :meth_b]ā€

Fixed at http://rubyforge.org/docman/view.php/735/2472/examples.html.

Thanks,

Dan

On 10/15/07, Yukihiro M. [email protected] wrote:

Matz
this is the link to the paper defining? traits, well it defines traits
pretty much as they
are defined in Squeak (and Scala AFAIK and maybe Fortress, not sure).

http://portal.acm.org/ft_gateway.cfm?id=1028771&type=pdf&coll=GUIDE&dl=GUIDE&CFID=7912496&CFTOKEN=77115102

On 10/15/07, Daniel B. [email protected] wrote:

Please see http://rubyforge.org/docman/view.php/735/309/README.html
and look at the synopsis. Ideas (and code) in that library also came
from Ara Howard and Mauricio Fā€¦

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

On 10/15/07, Trans [email protected] wrote:
>

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

Robert D. wrote:

and look at the synopsis. Ideas (and code) in that library also came
from Ara Howard and Mauricio Fā€¦

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

On Oct 15, 8:38 am, Yukihiro M. [email protected] wrote:

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.

On 10/16/07, Daniel B. [email protected] wrote:

|inheritance chain? Thatā€™s interesting.
Please see http://rubyforge.org/docman/view.php/735/309/README.html
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.

> > 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

On Oct 15, 8:11 am, Yukihiro M. [email protected] wrote:

If I knew traits before designing Ruby, Iā€™d have chosen traits over
modules. But thatā€™s the life.

I have to agree that traits are too much alike and yet too different
from modules to co-exist in the same language. However, I disagree
with this subsequent statement. Much of the benefit of traits can
still be had by overlaying the same concepts on Rubyā€™s modules. In the
end I think the most important part is usability, not so much the
underlying implementation (as long as it is reasonably efficient, of
course). Moreover, I contend that if you are serious when you say, you
would have used traits instead of modules if he had known about them,
then you were fortunate not to have known, b/c modules are a more
powerful composition mechanism, despite their greater implementation
complexity.

To demonstrate my point here is Facetsā€™ module/traits.rb lib. I
improved it a fair bit yesterday --thanks to Robert and this thread.
Iā€™d like others to have a look and provide any feedback. As you will
see in the code, I still have a couple questions about where to use
public vs. all instance methods (which leads me to question/thought
that I will bring up in another thread). Here you goā€¦

class Module

# Combine modules.

def +(other)
  base = self
  Module.new do
    include base
    include other
  end
end

# Subtract modules.
#--
# TODO Should this use all instance_methods, not just public?
#++
def -(other)
  case other
  when Array
    subtract = instance_methods(true) & other.collect{|m| m.to_s}
  when Module
    subtract = instance_methods(true) &

other.instance_methods(true) # false?
when String, Symbol
subtract = instance_methods(true) & [other.to_s]
end
base = self
Module.new do
include base
subtract.each{ |x| undef_method x }
end
end

# Rename methods.

def *(rename_map)
  base = self
  Module.new do
    include base
    rename_map.each do |from, to|
      alias_method to, from
      undef_method from
    end
  end
end

# Detect conflicts.
#--
# TODO All instance methods, or just public?
#++
def conflict?(other)
  c = []
  c += (public_instance_methods(true) &

other.public_instance_methods(true))
c += (private_instance_methods(true) &
other.private_instance_methods(true))
c += (protected_instance_methods(true) &
other.protected_instance_methods(true))
c.empty ? false : c
end

#def conflict?(other)
#  c = instance_methods & other.instance_methods
#  c.empty ? false : c
#end

def public_conflict?(other)
  c = public_instance_methods(true) &

other.public_instance_methods(true)
c.empty ? false : c
end

def private_conflict?(other)
  c = private_instance_methods(true) &

other.private_instance_methods(true)
c.empty ? false : c
end

def protected_conflict?(other)
  c = protected_instance_methods(true) &

other.protected_instance_methods(true)
c.empty ? false : c
end

end

Thanks,
T.