Why does Module#include exclude the module's metaclass?

Discussion in 'Ruby' started by John Mair, Oct 7, 2010.

  1. John Mair

    John Mair Guest

    When classes are inherited in Ruby the singleton classes are also
    inherited:

    class A
    def self.hello
    puts "hello"
    end
    end

    class B < A
    end

    B.hello #=> "hello"
    Yet with modules, this is not the case:

    module M
    def self.goodbye
    puts "goodbye"
    end
    end

    class A
    include M
    end

    A.goodbye #=> NameError
    To get around this limitation many ppl resort to this ugly hack:

    module M
    def self.included(c)
    c.extend ClassMethods
    end

    module ClassMethods
    def goodbye
    puts "goodbye"
    end
    end
    end
    Ok, so my question: is there a theoretical/conceptual reason behind this
    limitation on modules? or was it just an implementation difficulty?

    After looking at the C source code (YARV/MRI) I can identify there is an
    implementation difficulty (not insurmountable, but one all the same),
    but is this the sole reason? Are there any other reasons for this
    limitation?

    thanks
    --
    Posted via http://www.ruby-forum.com/.
    John Mair, Oct 7, 2010
    #1
    1. Advertising

  2. John Mair

    botp Guest

    On Thu, Oct 7, 2010 at 7:33 AM, John Mair <> wrote:
    > When classes are inherited in Ruby the singleton classes are also
    > inherited:
    >
    > class A
    > =A0def self.hello
    > =A0 =A0puts "hello"
    > =A0end
    > end
    >
    > class B < A
    > end
    >
    > B.hello #=3D> "hello"


    ok. single inheritance

    > Yet with modules, this is not the case:
    >
    > module M
    > =A0def self.goodbye
    > =A0 =A0puts "goodbye"
    > =A0end
    > end
    >
    > class A
    > =A0include M
    > end
    >
    > A.goodbye #=3D> NameError



    class A
    include M
    include N
    end

    now, which goodbye??

    > To get around this limitation many ppl resort to this ugly hack:


    sorry, ' prefer specs over hacks :)

    module ClassMethods
    def goodbye
    puts "goodbye"
    end
    end
    #=3D> nil

    class A
    class << self
    include ClassMethods
    end
    end
    #=3D> #<Class:A>

    A.goodbye
    goodbye

    clearer, if i may say.

    best regards -botp
    botp, Oct 7, 2010
    #2
    1. Advertising

  3. John Mair

    John Mair Guest

    Hehe,

    I don't know which question you were answering but it definitely wasn't
    mine! :)

    I asked why, when including a module, the singleton class is not also
    included. Whereas when performing class inheritance the singleton IS
    inherited.

    I am just curious to the difference in behaviour; as I can't think of a
    reason why module inclusion would work differently to class inheritance
    :(

    John

    botp wrote:
    > On Thu, Oct 7, 2010 at 7:33 AM, John Mair <> wrote:
    >> end
    >>
    >> B.hello #=> "hello"

    >
    > ok. single inheritance
    >
    >> end
    >>
    >> A.goodbye #=> NameError

    >
    >
    > class A
    > include M
    > include N
    > end
    >
    > now, which goodbye??
    >
    >> To get around this limitation many ppl resort to this ugly hack:

    >
    > sorry, ' prefer specs over hacks :)
    >
    > module ClassMethods
    > def goodbye
    > puts "goodbye"
    > end
    > end
    > #=> nil
    >
    > class A
    > class << self
    > include ClassMethods
    > end
    > end
    > #=> #<Class:A>
    >
    > A.goodbye
    > goodbye
    >
    > clearer, if i may say.
    >
    > best regards -botp


    --
    Posted via http://www.ruby-forum.com/.
    John Mair, Oct 7, 2010
    #3
  4. John Mair

    botp Guest

    On Thu, Oct 7, 2010 at 8:59 AM, John Mair <> wrote:
    > I asked why, when including a module, the singleton class is not also
    > included. Whereas when performing class inheritance the singleton IS
    > inherited.
    > I am just curious to the difference in behaviour; as I can't think of a
    > reason why module inclusion would work differently to class inheritance
    > :(


    single inheritance for class includes their singletons. single class
    inclusion easy to track.
    mixin is many modules inclusion. if ruby includes mods singletons,
    then it would not be different to multiple inheritance, no. difficult
    to track on dynamic lang. ..confusing as to design of ruby... matz
    has final say

    best regards -botp
    botp, Oct 7, 2010
    #4
  5. John Mair

    John Mair Guest

    Thanks for your reply.

    But this argument seems too subtle for me.

    1) I agree that singleton class of the module is actually a 'class' but
    (if we allowed this behavior) it would only be included when and only
    when the module is included. We can just consider this a special
    exception, no?

    This exception would only apply to singleton class of modules, of
    course, normal classes cannot be included in this way.

    2) Given that class inheritance does include the singleton, do you not
    think it 'surprising' that module inclusion does not? I found it
    surprising.

    3) Many people get around this limitation in module inclusion by abusing
    the included() hook and then extending a ClassMethods submodule, I think
    this is ugly.

    3) Out of curiosity, are there any other reasons (besides the one you
    gave) for why modules do not include the singleton? What reason did Matz
    give?

    Thanks in advance,

    John


    Urabe Shyouhei wrote:
    > (2010/10/07 8:33), John Mair wrote:
    >> Ok, so my question: is there a theoretical/conceptual reason behind this
    >> limitation on modules? or was it just an implementation difficulty?

    >
    > The former.
    >
    > 1) So-called "class methods" are singleton methods of those Class class
    > instances.
    >
    > 2) A module's class methods are hence, singleton methods of a Module
    > class
    > instance. To say it in another word, they are instance methods of the
    > singleton class of such module.
    >
    > 3) So if you want a module inclusion to cause somewhat injecting a
    > module's
    > singleton methods into a class's, there should be this relationship:
    >
    > +---------+ +---------+
    > | Meta A +---> Meta M |
    > +----^----+ +----^----+
    > | |
    > +--+--+ +--+--+
    > | A +-------> M |
    > +-----+ +-----+
    >
    > 4) But this is impossible, because Meta M is a class. A class cannot be
    > included into another class.


    --
    Posted via http://www.ruby-forum.com/.
    John Mair, Oct 7, 2010
    #5
  6. John Mair

    Intransition Guest

    On Oct 6, 7:33=A0pm, John Mair <> wrote:
    > When classes are inherited in Ruby the singleton classes are also
    > inherited:
    >
    > class A
    > =A0 def self.hello
    > =A0 =A0 puts "hello"
    > =A0 end
    > end
    >
    > class B < A
    > end
    >
    > B.hello #=3D> "hello"
    > Yet with modules, this is not the case:
    >
    > module M
    > =A0 def self.goodbye
    > =A0 =A0 puts "goodbye"
    > =A0 end
    > end
    >
    > class A
    > =A0 include M
    > end
    >
    > A.goodbye #=3D> NameError
    > To get around this limitation many ppl resort to this ugly hack:
    >
    > module M
    > =A0 def self.included(c)
    > =A0 =A0 c.extend ClassMethods
    > =A0 end
    >
    > =A0 module ClassMethods
    > =A0 =A0 def goodbye
    > =A0 =A0 =A0 puts "goodbye"
    > =A0 =A0 end
    > =A0 end
    > end
    > Ok, so my question: is there a theoretical/conceptual reason behind this
    > limitation on modules? or was it just an implementation difficulty?
    >
    > After looking at the C source code (YARV/MRI) I can identify there is an
    > implementation difficulty (not insurmountable, but one all the same),
    > but is this the sole reason? Are there any other reasons for this
    > limitation?


    For no good reason other than a purely theoretical misconception
    concerning single vs multiple inheritance --at least that's the only
    reason I have ever been able to derive from my countless inquiries
    I've made into the subject.

    Over the years I have become increasing convinced that the distinction
    between class and module in Ruby is simply an artifice that inhibits
    the language unduly.
    Intransition, Oct 7, 2010
    #6
  7. John Mair

    botp Guest

    On Thu, Oct 7, 2010 at 12:31 PM, Intransition <> wrote:
    > For no good reason other than a purely theoretical misconception
    > concerning single vs multiple inheritance --at least that's the only
    > reason I have ever been able to derive from my countless inquiries
    > I've made into the subject.
    >
    > Over the years I have become increasing convinced that the distinction
    > between class and module in Ruby is simply an artifice that inhibits
    > the language unduly.


    matz has humbly commented on this...

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

    and was open and kind enough...

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


    best regards -botp
    botp, Oct 7, 2010
    #7
  8. John Mair

    John Mair Guest

    @Thomas,

    I agree, in fact I wrote a little C extension to bring this
    functionality to modules http://github.com/banister/real_include
    Use it like this:

    module M
    def self.hello
    puts "hello from class"
    end

    def bye
    puts "bye from instance"
    end
    end

    class A
    real_include M
    end

    A.hello #=> "hello from class"
    A.new.bye #=> "bye from instance"

    I would love to hear from Matz himself why this limitation is built in;
    as most of the explanations i've heard have just been along the lines of
    "that's not how modules work". In my opinion the current behavior does
    violate the principle of least surprise.

    @botp

    Thanks for the links :) But I don't see how they are on point at all.
    He's talking there about a 'traits' system, he didn't say *anything*
    about traits bringing in singleton methods or not. Sorry but i can't see
    the relevance :( (though maybe i just don't know enough about traits?!)

    John

    Thomas Sawyer wrote:
    > On Oct 6, 7:33�pm, John Mair <> wrote:
    >> end
    >> class A
    >>
    >> implementation difficulty (not insurmountable, but one all the same),
    >> but is this the sole reason? Are there any other reasons for this
    >> limitation?

    >
    > For no good reason other than a purely theoretical misconception
    > concerning single vs multiple inheritance --at least that's the only
    > reason I have ever been able to derive from my countless inquiries
    > I've made into the subject.
    >
    > Over the years I have become increasing convinced that the distinction
    > between class and module in Ruby is simply an artifice that inhibits
    > the language unduly.


    --
    Posted via http://www.ruby-forum.com/.
    John Mair, Oct 7, 2010
    #8
  9. John Mair

    John Mair Guest

    @Urabe,

    sorry if my reply seemed rude or snarky, i did not mean it that way :)

    yeah #ancestors behave strange with real_include, I think this is due to
    the fact that normal T_ICLASS store the actual module in the klass
    pointer but real_include store a singleton class there, which #ancestors
    does not expect.

    I think the best approach (if real_include or something like it accepted
    as a patch) would be to store the actual module in a hidden __module__
    instance variable on the ICLASS (just like __attached__ for singleton
    class) and #ancestors can look at this instead of klass pointer.

    I can see some other arguments for not bringing in module singleton
    methods with #include, one for example is that the hook methods
    included() and extended() will be accessible to the class too, which is
    ugly.

    I think there are OK arguments either way; but it's not such a serious
    issue really - to be honest i was just curious why it is that way :)

    Thanks for your time:)

    John

    Urabe Shyouhei wrote:
    > (2010/10/07 10:59), John Mair wrote:
    >> 1) I agree that singleton class of the module is actually a 'class' but
    >> (if we allowed this behavior) it would only be included when and only
    >> when the module is included. We can just consider this a special
    >> exception, no?
    >>
    >> This exception would only apply to singleton class of modules, of
    >> course, normal classes cannot be included in this way.

    >
    > So you were actually not asking why, but claiming this is wrong. Not
    > sure for
    > that. Your real_include gem breaks Class#ancestor in a strange way so I
    > guess
    > there are some pitfalls, though noting particular.
    >
    >> 2) Given that class inheritance does include the singleton, do you not
    >> think it 'surprising' that module inclusion does not? I found it
    >> surprising.

    >
    > Tips: principle of least surprise is a wrong way for you to persuade
    > matz
    > because at any moment he can say "I don't think so". Try a different
    > route.
    >
    >> 3) Many people get around this limitation in module inclusion by abusing
    >> the included() hook and then extending a ClassMethods submodule, I think
    >> this is ugly.

    >
    > Maybe. But I think a module's having class method is itself ugly. It
    > tends
    > to smell like a API design mistake. I would recommend you to rethink
    > why you
    > need such things.
    >
    >> 3) Out of curiosity, are there any other reasons (besides the one you
    >> gave) for why modules do not include the singleton? What reason did Matz
    >> give?

    >
    > No, I do not know other reasons. It is rather obvious to me. Of course
    > that
    > does not ensure there is not reason though.


    --
    Posted via http://www.ruby-forum.com/.
    John Mair, Oct 7, 2010
    #9
    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. ironfroggy
    Replies:
    16
    Views:
    431
    Michele Simionato
    Jun 3, 2005
  2. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,769
    Smokey Grindel
    Dec 2, 2006
  3. Andreas Bogenberger
    Replies:
    3
    Views:
    891
    Andreas Bogenberger
    Feb 22, 2008
  4. Ruki
    Replies:
    1
    Views:
    337
    dizzy
    Jul 10, 2008
  5. Steven D'Aprano

    Metaclass of a metaclass

    Steven D'Aprano, Jun 5, 2012, in forum: Python
    Replies:
    1
    Views:
    299
Loading...

Share This Page