include Module in another Module

B

Brian Buckley

What is the proper syntax/code to include a Module into another
Module? My attempt below is not working.

--Brian

module Foo
def xxx; "this is xxx" end
end

module Enumerable
include Foo
end

puts [].xxx #does not work, xxx not defined for Array. Array
includes Enumerable, right?
 
P

Pit Capitain

Brian said:
What is the proper syntax/code to include a Module into another
Module? My attempt below is not working.

module Foo
def xxx; "this is xxx" end
end

module Enumerable
include Foo
end

puts [].xxx #does not work, xxx not defined for Array. Array
includes Enumerable, right?

Brian, this isn't a problem of your syntax/code, but a (well known)
problem of the Ruby interpreter. There's no known solution yet. You have
to change the Enumerable module directly.

Regards,
Pit
 
B

Brian Buckley

Thanks, Pit.

Rounding this out, I notice now that classes that "include Enumerable"
after Enumerable is enhanced by "include Foo" have the extra method,
but classes that "include Enumerable" before Enumerable is enhanced
don't (core class Array is in this category).

Interesting to learn this behavior is considered a bug, and may one
day be fixed.

Interestingly, re-including Enumerable to Array, i.e., the line

class Array; include Enumerable end

corrects the bug for Array --- this is not necessarily a useful thing
to know since as you suggest putting code directly into Enumerable
rather than by using an include appears to be the way to go here.

--Brian


Brian said:
What is the proper syntax/code to include a Module into another
Module? My attempt below is not working.

module Foo
def xxx; "this is xxx" end
end

module Enumerable
include Foo
end

puts [].xxx #does not work, xxx not defined for Array. Array
includes Enumerable, right?

Brian, this isn't a problem of your syntax/code, but a (well known)
problem of the Ruby interpreter. There's no known solution yet. You have
to change the Enumerable module directly.

Regards,
Pit
 
M

Marcello Barnaba

Hi,

(i'm no ruby internals expert, just having some fun poking at rhg[2])

Thanks, Pit.
Interesting to learn this behavior is considered a bug, and may one
day be fixed.

It is due the way method inheritance is implemented right now.

In MRI, every object has a linked list of classes from which inherits methods.
This list contains either "plain" ruby classes, and other "hidden"
metaclasses, that serve to purposes such as singleton methods, class methods
and module inclusion[1].
The latter is implemented by inserting in the linked list a new "include
class" whose mehtod table points to the included module's method table.
This means that when you do

class A
include M
end

the ruby interpreter will build such an inheritance list:

M
|
|
A -> (iM) -> Object

so, instances of A will have access to M's methods via the iM include class.

When you do

module M1
end
module M2
include M1
end

class A
include M2
end

two include classes are created for A, pointing to every module in the chain:

+-------> M2
| |
| (iM2)
| |
| M1
| |
A -> (iM2') -> (iM1) -> Object

... that's why:
Interestingly, re-including Enumerable to Array, i.e., the line

class Array; include Enumerable end

... fixes the problem, because this include causes the include class of your
module to be added to Array's inheritance chain ...
corrects the bug for Array --- this is not necessarily a useful thing
to know since as you suggest putting code directly into Enumerable
rather than by using an include appears to be the way to go here.

... and also why adding code to enumerable works, because you are changing the
method table already pointed by the include class in Array's inheritance
linked list.

Ruby internals are really really beautiful :)

[1]: http://www.ruby-doc.org/core/classes/Class.html
[2]: http://rhg.rubyforge.org/chapter04.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top