include Module in another Module

Discussion in 'Ruby' started by Brian Buckley, Feb 19, 2007.

  1. 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?
    Brian Buckley, Feb 19, 2007
    #1
    1. Advertising

  2. Brian Buckley

    Pit Capitain Guest

    Brian Buckley schrieb:
    > 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
    Pit Capitain, Feb 19, 2007
    #2
    1. Advertising

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


    On 2/19/07, Pit Capitain <> wrote:
    > Brian Buckley schrieb:
    > > 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
    >
    >
    Brian Buckley, Feb 20, 2007
    #3
  4. Hi,

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

    On Tuesday 20 February 2007 02:59, Brian Buckley wrote:
    > 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
    --
    pub 1024D/8D2787EF 723C 7CA3 3C19 2ACE 6E20 9CC1 9956 EB3C 8D27 87EF
    Marcello Barnaba, Feb 20, 2007
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Danny Anderson
    Replies:
    5
    Views:
    483
    Victor Bazarov
    Aug 15, 2003
  2. Rolf Magnus
    Replies:
    2
    Views:
    587
    Karl Heinz Buchegger
    Nov 28, 2003
  3. Elie Nader
    Replies:
    1
    Views:
    625
  4. Aguilar, James
    Replies:
    2
    Views:
    675
    Aguilar, James
    Jul 16, 2004
  5. Andreas Bogenberger
    Replies:
    3
    Views:
    885
    Andreas Bogenberger
    Feb 22, 2008
Loading...

Share This Page