Why the lack of mixing-in support for Class methods?

On Wed, 14 Jun 2006 [email protected] wrote:

On Jun 13, 2006, at 10:38 AM, Yukihiro M. wrote:

I don’t think I understand you. Do you want to allow #include to
include classes? Without making it MI? Hmm.

It isn’t altogether obvious to me why a class passed to #include couldn’t be
interpreted as a module (since instances of Class are instances of Module
via inheritance).

module M
def initialize
‘ha’
end
end

module N
def initialize
‘ha ha’
end
end

class C
include M
include N
def initialize
‘hmmm’
end
end

with classes, this is always the situation. obviously it can be
dealt
with - but it’s a little less straight forward than the ‘normal’ mixin
effect.

not for or against here - but i do believe being able to mixin classes,
without some really slick handling of super/initialize, state, and
class_init
on ruby’s part would be confusing for most. in otherwords, ruby would
need to
become mi to do so.

regards.

-a

On Jun 13, 2006, at 12:50 PM, [email protected] wrote:

end
be dealt
with - but it’s a little less straight forward than the ‘normal’
mixin effect.

I don’t see how your example is any different than the problem
presented by
nested includes. The ordering of ancestors and thus the resolution
of method
lookup is well defined in either case, no?

not for or against here - but i do believe being able to mixin
classes,
without some really slick handling of super/initialize, state, and
class_init
on ruby’s part would be confusing for most. in otherwords, ruby
would need to
become mi to do so.

Isn’t this already an issue with module-only includes? There was some
discussion on this recently I think.

We got to this point in the discussion because of the desire to auto-
mixin
module methods, which happen to reside inside a singleton class.
So this
raised the question of what does it mean to include a class? I still
don’t
like the idea of auto-mixin of module methods but to make sense of
that idea
you must somehow grapple with the notion that instance methods can
be implicitly extracted from a singleton class object (i.e. an
instance of Class).
Once you go down that road, it just begs the question of why you
can’t do that
with any class object.

Gary W.

Hi,

In message “Re: Why the lack of mixing-in support for Class methods?”
on Wed, 14 Jun 2006 02:31:00 +0900, [email protected] writes:

|> I don’t think I understand you. Do you want to allow #include to
|> include classes? Without making it MI? Hmm.
|
|No no. You’d still only be able to include modules. I’m thinking a
|module’s “singleton class” could be a “singleton module”, so to speak,
|instead. It’s a bit difficult to communicate b/c the terminology is
|caught up in how it curently works. But it’s a lot less fancy than I
|think it sounds.

That makes modules too “special”. Every object has its own “singleton
class” (aka eigenclass) no matter what class it belongs to, under the
current implementation. After your proposal, modules should be
treated specially not to have ordinary singleton classes. I know its
purpose (to allow injecting a module’s singleton methods using
#include), but I am not sure if it’s worth making object model
complex.

It seems Daniel’s API is good enough. What’s wrong with the idea?
Except for implementation issues, of course.

						matz.

On Wed, 14 Jun 2006 [email protected] wrote:

I don’t see how your example is any different than the problem presented by
nested includes. The ordering of ancestors and thus the resolution of
method lookup is well defined in either case, no?

yes. the problem is that mixin modules, by design, seldom have name
collisions with important instance methods, while mixin classes, if they
existed, always would. it’s a matter of degrees.

regards.

-a

On Wed, 14 Jun 2006 [email protected] wrote:

tom - you’ll love this

http://www.jave.de/

cheers.

-a

are you looking for that here?

module MixInClassMethods
def test
puts “test”
end
end

try using ‘extend’

class MyClass
extend MixInClassMethods
end

MyClass.test
“test”

Andrew S. schrieb:

Yukihiro M. wrote:

That makes modules too “special”. Every object has its own “singleton
class” (aka eigenclass) no matter what class it belongs to, under the
current implementation. After your proposal, modules should be
treated specially not to have ordinary singleton classes. I know its
purpose (to allow injecting a module’s singleton methods using
#include), but I am not sure if it’s worth making object model
complex.

I see your point. This solution is kind of drastic in that respect.
Although I sort of liked the symmetry of a module being a module from
“head-to-toe” :wink: And it’s knid of too bad too, b/c this solution
limited the capability just to module’s class-level, where it’s needed
and no where else. Other solutions tend to be much broader and/or
hackish.

It seems Daniel’s API is good enough. What’s wrong with the idea?
Except for implementation issues, of course.

Well, that’s what I’ve been using already. In fact, as far as I can
tell the Facets’ implementation is the most complete around (not to say
it can’t be improved). But even so, it is hackish, inefficient, and
fragile, and that really can;t be hellped because of the naturr of
implementing it. And its’ made worse in that the techinque is without
standard, so nayone can run roughshod right over it. These are the
reasons why I’ve asked you directly about the issue. I’m essentially at
my wits end with it. I’ve spent more hours on this one problem than I
care to admit.

This evening is sadly no exception. I attempted another implementation,
which I think has a better overall interface (not as good as just being
able to include the singleton, but…)

module M
def meta.x
self
end
end

class X
meta_include M
end

X.x #=> X

Alas, an implementation of this appears to be impossible. Again those
singleton methods are just out of reach and it is frustrating to no
end.

T.

Hi,

In message “Re: Why the lack of mixing-in support for Class methods?”
on Wed, 14 Jun 2006 11:53:32 +0900, [email protected] writes:

|> It seems Daniel’s API is good enough. What’s wrong with the idea?
|> Except for implementation issues, of course.
|
|Well, that’s what I’ve been using already. In fact, as far as I can
|tell the Facets’ implementation is the most complete around (not to say
|it can’t be improved). But even so, it is hackish, inefficient, and
|fragile, and that really can;t be hellped because of the naturr of
|implementing it. And its’ made worse in that the techinque is without
|standard, so nayone can run roughshod right over it. These are the
|reasons why I’ve asked you directly about the issue. I’m essentially at
|my wits end with it. I’ve spent more hours on this one problem than I
|care to admit.

You got me wrong again. I asked you what if I’d add Daniel’s API to
the core.

						matz.

Yukihiro M. wrote:

|it can’t be improved). But even so, it is hackish, inefficient, and
|fragile, and that really can;t be hellped because of the naturr of
|implementing it. And its’ made worse in that the techinque is without
|standard, so nayone can run roughshod right over it. These are the
|reasons why I’ve asked you directly about the issue. I’m essentially at
|my wits end with it. I’ve spent more hours on this one problem than I
|care to admit.

You got me wrong again. I asked you what if I’d add Daniel’s API to
the core.

Ah yea, sorry for rambling. As I said, I already use that API, so, yea,
that works. I just don’t know the best solution and have been throwing
out ideas. I was hoping maybe you could tell us.

So if you did this, would #include handle the extending? Or would
another method need to be used?

T.

Well, I hate to throw a wrench in the works at this point, but (by
God’s grace) I may have managed a better solution. It can be
implemented in either of two ways. Either by extending module with some
special methods like so:

class Module

def propagating_extensions
  @propagating_extensions ||= []
end

def propagate( *mods )
  propagating_extensions.concat mods
end

def extend_and_propagate( *mods )
  propagate *mods
  extend *mods
end

alias_method :append_features_without_propagation, :append_features

def append_features( base )
  unless propagating_extensions.empty?
    base.extend_and_propagate *propagating_extensions
  end
  append_features_without_propagation( base )
end

end

Or alternatively sepearating the capability into a subclass of module:

class Capsule < Module

def extensions
  @extensions ||= []
end

def propagate( *mods )
  extensions.concat mods
end

def extend( *mods )
  propagate *mods
  super
end

def append_features( base )
  unless extensions.empty?
    base.extend *extensions
  end
  super
end

end

The later is a little more elegant in implementation but requires the
use of the specialized class to continue the propogating behavior. The
former doesn’t need the special class, but does require an additional
special method.

Here’s an example of using the first implementation.

module Foo
def foo ; “foo” ; end
end

module Bar
extend_and_propagate Foo
end

class X
include Bar
end

p X.foo #=> “foo”

And here’s an example of the second:

module Foo
def foo ; “foo” ; end
end

Bar = Capsule.new do
extend Foo
end

class X
include Bar
end

p X.foo #=> “foo”

T.

On 6/13/06, Yukihiro M. [email protected] wrote:

module Moo
def im
end

class_extension do

Maybe it could be called class_methods ?

Foo.im
Do you mean Foo.cm ?

The name ‘class_extension’ may be changed in the real implementation,
or maybe it would be a new visibility.

Is this just a more automatic/nicer way to do:

module Moo
def self.included mod
mod.extend ClassMethods
end
module ClassMethods
def cm
end
end
def im
end
end

class Foo
include Moo
end

?

It does seem a bit more convenient.

Phil

Hi,

In message “Re: Why the lack of mixing-in support for Class methods?”
on Wed, 14 Jun 2006 13:36:34 +0900, [email protected] writes:

|So if you did this, would #include handle the extending? Or would
|another method need to be used?

I thinking of something like the following:

module Moo
def im
end

class_extension do
  def cm
  end
end

end

class Foo
include Foo
end
foo = Foo.new
foo.im
Foo.im

The name ‘class_extension’ may be changed in the real implementation,
or maybe it would be a new visibility.

						matz.

[email protected] wrote:

X.x #=> X
I’ve been down that road myself, trying something like this:

module A
def this.foo
“foo”
end
end

But sadly, I found it impossible. Maybe I’ll give it another try today.

Cheers,
Daniel

Hi,

In message “Re: Why the lack of mixing-in support for Class methods?”
on Wed, 14 Jun 2006 15:34:43 +0900, “Phil T.”
[email protected] writes:

|> class_extension do
|
|Maybe it could be called class_methods ?

I thought of the name first, but I changed my mind because it is too
similar to methods with different behavior e.g. private_methods.
Besides that class_extension can be used for something other than
methods, for example, constant definition.

|> Foo.im
|
|Do you mean Foo.cm ?

Yes. What a shame.

|Is this just a more automatic/nicer way to do:
|
|module Moo
| def self.included mod
| mod.extend ClassMethods
| end
| module ClassMethods
| def cm
| end
| end
| def im
| end
|end
|
|class Foo
| include Moo
|end
|
|?

Maybe. I am not opposing to this style.

|It does seem a bit more convenient.

How is it more convenient?

						matz.

On Jun 14, 2006, at 1:34 AM, Phil T. wrote:

module Moo
def im
end

class_extension do

Maybe it could be called class_methods ?

I think that name misrepresents what the method does.

James Edward G. II

James Edward G. II wrote:

|module Moo
|
|class Foo
| include Moo
|end
|
|?

Maybe. I am not opposing to this style.

I think I still prefer this approach, though the method thing is OK
with me too (as long as we don’t call it class_methods()).

If you allow #class_extension (or whatever you want to call it) to also
take a list of modules in addition to the block, then you’d effectively
have it both ways. Ex-

module Moo
module ClassMethods
def cm
end
end
class_extension ClassMethods
end

T.

On Jun 14, 2006, at 1:48 AM, Yukihiro M. wrote:

| mod.extend ClassMethods
| include Moo
|end
|
|?

Maybe. I am not opposing to this style.

I think I still prefer this approach, though the method thing is OK
with me too (as long as we don’t call it class_methods()).

James Edward G. II

Yukihiro M. wrote:

I think class_extension (or whatever) plus and include will do.

Nice point.

Okay, so I’m wondering, will the annonymous module this creates get a
name of some sort instead of the ususal “#Module:0xb7ca7e1c” and if
the class_extension method is used more than once will it create an
additional new module or just reuse the first?

Thanks,
T.

Hi,

In message “Re: Why the lack of mixing-in support for Class methods?”
on Wed, 14 Jun 2006 23:30:25 +0900, [email protected] writes:

|Okay, so I’m wondering, will the annonymous module this creates get a
|name of some sort instead of the ususal “#Module:0xb7ca7e1c” and if
|the class_extension method is used more than once will it create an
|additional new module or just reuse the first?

I am not thinking about implementation detail yet. What do you think
how it should behave?

						matz.

On Jun 14, 2006, at 10:30 AM, [email protected] wrote:

Okay, so I’m wondering, will the annonymous module this creates get a
name of some sort instead of the ususal “#Module:0xb7ca7e1c

I was thinking that the block would just be evaluated in the context of
the targeted singleton class as vs. the context of a new anonymous
module which is then included into the targeted singleton class.

Gary W.