Module include matters?

Hi,

I was playing with various modules and found something I can't
explain. It seems like module inclusion's order matters ? Here is a
simple test case :

module B; end
module C; include B; end

module A; def somemethod; end; end
#reopening
module B; include A; end

p B.instance_methods #=> ["somemethod"]
p C.instance_methods #=> [] ???

I don't understand why C doesn't inherit A's instance_methods. Does
somebody know something about that ?

···

--
Cheers,
  zimbatm

http://zimbatm.oree.ch

Hello,

I was playing with various modules and found something I can't
explain. It seems like module inclusion's order matters ? Here is a
simple test case :

[Snip example]

I don't understand why C doesn't inherit A's instance_methods. Does
somebody know something about that ?

Yes, I asked a similar version of this question in [ruby-talk:121118]

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/121118

Pit Capitain provided a good summary and link to further details in
[ruby-talk:121191]

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/121191

I hope this helps,
Zev

···

On Tue, 20 Jun 2006 07:32:22 +0900, Jonas Pfenniger <zimba.tm@gmail.com> wrote:

This is called the "Dyanmic Module Inclusion Problem". And Pit is
right, it is an implmentation issue. I think Matz would love to have a
fix for it, but appearently it is difficult, if not impossible, to do
so efficiently,

T.

Thanks both of you for your insight. I've created a small hack to fix that issue

class Module
  # Weird hack to ensure deep inclusion of modules
  def include_deep(mod)
    include mod
    ancestors[1..-1].select do |a|
      a != mod and not a.ancestors.include?(mod)
    end.each { |a| a.include_deep(mod) }
  end
end

···

--
Cheers,
  zimbatm

http://zimbatm.oree.ch

Jonas Pfenniger wrote:

Thanks both of you for your insight. I've created a small hack to fix that issue

class Module
  # Weird hack to ensure deep inclusion of modules
  def include_deep(mod)
    include mod
    ancestors[1..-1].select do |a|
      a != mod and not a.ancestors.include?(mod)
    end.each { |a| a.include_deep(mod) }
  end
end

Hmm... Doesn't seem to do anything. Notice even without the above one
can instantiate a class and the mothod will "magically" showup. From
your example:

  class X
    include B
  end

  X.new.somemethod

T.

Hmm right, let me correct that

···

On 20/06/06, transfire@gmail.com <transfire@gmail.com> wrote:

Hmm... Doesn't seem to do anything. Notice even without the above one
can instantiate a class and the mothod will "magically" showup. From
your example:

doh' I would need to find the children and not the ancestors [C] of
the module (B) in which in include the other (A)... I guess it's
doable by browsing the ObjectSpace but it's quite expensive. If only
modules and classes would also list their childrens. Which is also
doable by overriding Module#included I guess but it's not really
reliable isn't it ?

···

On 20/06/06, Jonas Pfenniger <zimba.tm@gmail.com> wrote:

On 20/06/06, transfire@gmail.com <transfire@gmail.com> wrote:
> Hmm... Doesn't seem to do anything. Notice even without the above one
> can instantiate a class and the mothod will "magically" showup. From
> your example:

Hmm right, let me correct that

--
Cheers,
  zimbatm

http://zimbatm.oree.ch