The Persnickety Order of Self Serving Modules

This one caught me off guard.

irb(main):001:0> module M
orb(main):002:1> def x; "x"; end
orb(main):003:1> end
=> nil
orb(main):005:0> module Q
orb(main):006:1> extend self
orb(main):007:1> include M
orb(main):008:1> end
=> Q
orb(main):009:0> Q.x
NoMethodError: undefined method `x' for Q:Module
from (orb):9
from :0

Why isn't the included #x coming along for the ride in the self extension of Q? This kind of dyanmicism is vital when dynamically loading behaviors. And so I suspect it must do with the dread Dynamic Module Inclusion Problem? And it would appear that I am right:

orb(main):012:0> module M
orb(main):013:1> def x; "x"; end
orb(main):014:1> end
=> nil
orb(main):015:0> module Q
orb(main):016:1> include M
orb(main):017:1> extend self
orb(main):018:1> end
=> Q
orb(main):019:0> Q.x
=> "x"

Yes, another of the edge cases. But the preponderance weighs heavy on the Coding Spirit. The Dynamic Module Inclusion Problem is getting old.


Pit said...

Tom, if you want an object to respond to the methods of a module, you have to *extend* the object with the module. Replace "include" with "extend" and your code should work.

lopex said...

But there is a slightly different issue:


Pit said...

lopex: yes, for many years I've been aware of the problem you mention, but couldn't find a solution yet. Tom's problem though is a different one (at least it seems to me).

a different tom said...

Howdy. Did your implementation of e4x for ruby ever go anywhere? It's a great idea.

tea42 said...

Hi Pit. Yea my example has no context, so I can see what your thinking. But I actually do want to use 'include'. I'm trying to show that the 'extend self' should have pulled in the inculded methods to class-level access --well, it would if it weren't for the dynamic inclusion issue. That's way it actually works in one order but not the other. At least that's what I think is going on here.