Why metaclasses?

Discussion in 'Ruby' started by James Coglan, Jun 19, 2008.

  1. James Coglan

    James Coglan Guest

    [Note: parts of this message were removed to make it a legal post.]

    Hello all,

    I've dug around a little bit here but can't quite find the answer I'm
    looking for. A little background, then I'll get to my question. I write
    JS.Class, which is a JavaScript library for doing OOP using Ruby idioms. The
    latest stable release bootstraps JavaScript prototypes to build classes with
    classical inheritance, mixins etc. It's got many commonly used Ruby
    features, including late-bound arguments-optional super(), hooks, include()
    and extend(), etc. You can see it here:

    http://svn.jcoglan.com/jsclass/tags/1.6.1/source/class.js

    There are some bugs in this that I'm trying to fix by doing a complete
    rewrite. Most notably, super() can only call superclasses, not mixins. In
    1.6, Module is a tiny syntactic hack around protecting a set of methods
    using closures. In the new version, Module is right at the core and
    everything else is implemented using it, so hopefully I'll end up with a
    more Ruby-like system. Classes use modules to store their instance methods,
    all objects have modules to manage singleton methods etc. The source is
    here:

    http://svn.jcoglan.com/jsclass/branches/modular/source/class.js

    I've come to this version by poking around in irb and trying to figure out
    how Ruby works. So in this rewrite, Module is a class, Class is a class that
    inherits from Module. My understanding is that Classes are essentially
    Modules that can be instantiated (i.e. they can create new Objects), and
    that class inheritance is just a special case of module inclusion. In
    JS.Classs I've got metaclasses, except they're actually modules because
    that's all I need: something to resolve method lookups etc. that cannot be
    instantiated. Turns out using Modules for all these things gets you a very
    long way, and teaches you something about inheritance.

    So anyway, this question has been really bugging me: in Ruby, how come
    metaclasses are just that: classes? Given that you cannot instantiate them,
    is there any reason why they need to be classes instead of just modules? I
    want this release to be as close to Ruby as possible so if I've seriously
    misunderstood something I'd rather be put right.


    --
    James Coglan
    James Coglan, Jun 19, 2008
    #1
    1. Advertising

  2. 2008/6/19 James Coglan <>:
    > So anyway, this question has been really bugging me: in Ruby, how come
    > metaclasses are just that: classes? Given that you cannot instantiate them,


    13:32:55 OPSC_Gold_bas_dev_R1.2.2$ irb
    Ruby version 1.8.6
    irb(main):001:0> x = Class.new
    => #<Class:0x7ff9ece4>
    irb(main):002:0> o = x.new
    => #<#<Class:0x7ff9ece4>:0x7ff9b56c>
    irb(main):003:0> o.class
    => #<Class:0x7ff9ece4>
    irb(main):004:0> o.class == x
    => true
    irb(main):005:0> x === o
    => true
    irb(main):006:0> y = Class.new x
    => #<Class:0x7ff81dc4>
    irb(main):007:0> y.superclass
    => #<Class:0x7ff9ece4>
    irb(main):008:0> y.superclass == x
    => true
    irb(main):009:0> u = y.new
    => #<#<Class:0x7ff81dc4>:0x7ff77518>
    irb(main):010:0> x === u
    => true
    irb(main):011:0> y === u
    => true

    irb(main):012:0> m = Module.new
    => #<Module:0x7ff6e058>
    irb(main):013:0> y.class_eval { include m }
    => #<Class:0x7ff81dc4>
    irb(main):014:0> m === u
    => true
    irb(main):015:0> y.ancestors
    => [#<Class:0x7ff81dc4>, #<Module:0x7ff6e058>, #<Class:0x7ff9ece4>,
    Object, Kernel]
    irb(main):016:0>

    > is there any reason why they need to be classes instead of just modules? I
    > want this release to be as close to Ruby as possible so if I've seriously
    > misunderstood something I'd rather be put right.


    See above. :)

    Kind regards

    robert

    --
    use.inject do |as, often| as.you_can - without end
    Robert Klemme, Jun 19, 2008
    #2
    1. Advertising

  3. James Coglan

    James Coglan Guest

    [Note: parts of this message were removed to make it a legal post.]

    > 13:32:55 OPSC_Gold_bas_dev_R1.2.2$ irb
    > Ruby version 1.8.6
    > irb(main):001:0> x = Class.new
    > => #<Class:0x7ff9ece4>
    > irb(main):002:0> o = x.new
    > => #<#<Class:0x7ff9ece4>:0x7ff9b56c>
    > irb(main):003:0> o.class
    > => #<Class:0x7ff9ece4>
    > irb(main):004:0> o.class == x
    > => true
    > irb(main):005:0> x === o
    > => true
    > irb(main):006:0> y = Class.new x
    > => #<Class:0x7ff81dc4>
    > irb(main):007:0> y.superclass
    > => #<Class:0x7ff9ece4>
    > irb(main):008:0> y.superclass == x
    > => true
    > irb(main):009:0> u = y.new
    > => #<#<Class:0x7ff81dc4>:0x7ff77518>
    > irb(main):010:0> x === u
    > => true
    > irb(main):011:0> y === u
    > => true
    >
    > irb(main):012:0> m = Module.new
    > => #<Module:0x7ff6e058>
    > irb(main):013:0> y.class_eval { include m }
    > => #<Class:0x7ff81dc4>
    > irb(main):014:0> m === u
    > => true
    > irb(main):015:0> y.ancestors
    > => [#<Class:0x7ff81dc4>, #<Module:0x7ff6e058>, #<Class:0x7ff9ece4>,
    > Object, Kernel]
    > irb(main):016:0>
    >


    So x is a class, y is a class that inherits from x (which is to say, y
    'includes' x as its first inclusion). o is an x, u is a y (and is therefore
    an x). Fine. y includes m, so now u is an m as well. y's ancestors are
    itself, m, x, Object and Kernel. Kernel is the root module, Object is the
    root class (and therefore includes Kernel). A module's (and therefore a
    class's) ancestors are itself and its included modules (and *their* included
    modules, depth first). For a class, this means its included modules, its
    superclass, its superclass's included modules, and so on.

    So far I can't see how this is inconsistent with using metamodules instead
    of metaclasses, and with class inheritance being a special case of module
    inclusion. With apologies for my apparent slow-wittedness, what am I
    missing?
    James Coglan, Jun 19, 2008
    #3
  4. On 20.06.2008 00:27, James Coglan wrote:
    > So far I can't see how this is inconsistent with using metamodules instead
    > of metaclasses, and with class inheritance being a special case of module
    > inclusion. With apologies for my apparent slow-wittedness, what am I
    > missing?


    Your quote: "Given that you cannot instantiate them [...]". :)

    Kind regards

    robert
    Robert Klemme, Jun 20, 2008
    #4
  5. Robert Klemme wrote:
    > Your quote: "Given that you cannot instantiate them [...]".


    What's wrong with that? You can't.
    >> m = class <<Object.new; self end

    => #<Class:#<Object:0xb7b17ae4>>
    >> m.new

    TypeError: can't create instance of virtual class
    from (irb):167:in `new'
    from (irb):167
    from :0
    >> m.allocate

    TypeError: can't create instance of virtual class
    from (irb):168:in `allocate'
    from (irb):168
    from :0


    --
    Jabber:
    ICQ: 205544826
    Sebastian Hungerecker, Jun 20, 2008
    #5
  6. James Coglan

    Calamitas Guest

    On Thu, Jun 19, 2008 at 3:23 PM, James Coglan <> wrote:
    > So anyway, this question has been really bugging me: in Ruby, how come
    > metaclasses are just that: classes? Given that you cannot instantiate them,
    > is there any reason why they need to be classes instead of just modules? I
    > want this release to be as close to Ruby as possible so if I've seriously
    > misunderstood something I'd rather be put right.


    Well, I don't think instantiability by itself is a requirement for a
    class. Binding is a class, but you can't instantiate it (yourself)
    either. Not quite the same, I know. The singleton pattern prohibits
    explicit instantiation. Again, slightly different maybe, although very
    much the same as in both cases there are somewhat artificial
    restrictions built in to enforce a concept.

    But do singleton modules make sense? Modules can be included in other
    classes, but it makes little sense to include a singleton module in
    another class because then it would no longer be a *singleton module*.
    So singleton modules would be unincludable modules.

    So what's better, uninstantiable classes are unincludable modules?
    Somewhat arbitrary choice, but as mentioned above, uninstantiable
    classes have precedent.

    My 2 cents...

    Peter
    Calamitas, Jun 20, 2008
    #6
  7. James Coglan

    James Coglan Guest

    [Note: parts of this message were removed to make it a legal post.]

    2008/6/20 Calamitas <>:

    > On Thu, Jun 19, 2008 at 3:23 PM, James Coglan <>
    > wrote:
    > > So anyway, this question has been really bugging me: in Ruby, how come
    > > metaclasses are just that: classes? Given that you cannot instantiate

    > them,
    > > is there any reason why they need to be classes instead of just modules?

    > I
    > > want this release to be as close to Ruby as possible so if I've seriously
    > > misunderstood something I'd rather be put right.

    >
    > Well, I don't think instantiability by itself is a requirement for a
    > class. Binding is a class, but you can't instantiate it (yourself)
    > either. Not quite the same, I know. The singleton pattern prohibits
    > explicit instantiation. Again, slightly different maybe, although very
    > much the same as in both cases there are somewhat artificial
    > restrictions built in to enforce a concept.
    >
    > But do singleton modules make sense? Modules can be included in other
    > classes, but it makes little sense to include a singleton module in
    > another class because then it would no longer be a *singleton module*.
    > So singleton modules would be unincludable modules.
    >
    > So what's better, uninstantiable classes are unincludable modules?
    > Somewhat arbitrary choice, but as mentioned above, uninstantiable
    > classes have precedent.




    Singleton classes cannot be 'included' either, which is to say they cannot
    be subclassed.

    irb(main):006:0> class SillyArray < Array
    irb(main):007:1> end
    => nil
    irb(main):009:0> s = SillyArray.new [1,2,3,4]
    => [1, 2, 3, 4]
    irb(main):011:0> s.class
    => SillyArray
    irb(main):012:0> s.class.superclass
    => Array
    irb(main):013:0> class MetaArray < [].metaclass
    irb(main):014:1> end
    TypeError: can't make subclass of virtual class
    from (irb):13
    from :0

    What I'm trying to get at is: given that you can't really do anything
    'classy' with a metaclass, it seems they could quite easily be modules
    instead, and this makes more sense to me as they are just objects that store
    methods. Why do they need to be this specific type of module (i.e. Class)?
    James Coglan, Jun 20, 2008
    #7
  8. 2008/6/20 Sebastian Hungerecker <>:
    > Robert Klemme wrote:
    >> Your quote: "Given that you cannot instantiate them [...]".

    >
    > What's wrong with that? You can't.


    Ah, we're running in that terminology issue again: for me Class is a
    (or rather "the") metaclass (because it is the class of a class) but
    it seems you and probably James as well mean what I am used to call
    "singleton class".

    So then, yes, those cannot be instantiated.

    Cheers

    robert

    --
    use.inject do |as, often| as.you_can - without end
    Robert Klemme, Jun 20, 2008
    #8
  9. James Coglan

    Calamitas Guest

    On Fri, Jun 20, 2008 at 10:48 AM, James Coglan <> wrote:
    > Singleton classes cannot be 'included' either, which is to say they cannot
    > be subclassed.
    >
    > irb(main):006:0> class SillyArray < Array
    > irb(main):007:1> end
    > => nil
    > irb(main):009:0> s = SillyArray.new [1,2,3,4]
    > => [1, 2, 3, 4]
    > irb(main):011:0> s.class
    > => SillyArray
    > irb(main):012:0> s.class.superclass
    > => Array
    > irb(main):013:0> class MetaArray < [].metaclass
    > irb(main):014:1> end
    > TypeError: can't make subclass of virtual class
    > from (irb):13
    > from :0
    >
    > What I'm trying to get at is: given that you can't really do anything
    > 'classy' with a metaclass, it seems they could quite easily be modules
    > instead, and this makes more sense to me as they are just objects that store
    > methods. Why do they need to be this specific type of module (i.e. Class)?


    I don't know why exactly --only Matz knows-- but IMO the choice is
    somewhat arbitrary because whichever is chosen, class or module, you
    have to take away some of its typical behaviors to have it be
    singletonsomething. My feeling is that we're better off having
    singleton *classes*. Modules can appear multiple times in the class
    hierarchy and because of that some of the methods on Module behave in
    a much less useful way (IMO) than the corresponding methods on Class,
    especially when navigating the class hierarchy using #ancestors for
    instance. Note that modules also suffer from the double/dynamic
    inclusion problem, so things like Object#extend, or class << a ;
    include M ; end would need some extra code to make things work like
    they do now.

    Just remembered this has been discussed before; take a look here:

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

    Peter
    Calamitas, Jun 20, 2008
    #9
  10. James Coglan

    Marc Heiler Guest

    > I don't know why exactly --only Matz knows-- but IMO the choice is
    > somewhat arbitrary because whichever is chosen, class or module, you
    > have to take away some of its typical behaviors to have it be
    > singletonsomething.


    At times I wanted a language that does away with the distinction between
    class and module and objects, and rather focuses on objects, and
    behaviour only, with an elegant syntax like ruby has (but less complex
    as a whole)
    --
    Posted via http://www.ruby-forum.com/.
    Marc Heiler, Jun 21, 2008
    #10
  11. James Coglan

    James Britt Guest

    Marc Heiler wrote:
    >> I don't know why exactly --only Matz knows-- but IMO the choice is
    >> somewhat arbitrary because whichever is chosen, class or module, you
    >> have to take away some of its typical behaviors to have it be
    >> singletonsomething.

    >
    > At times I wanted a language that does away with the distinction between
    > class and module and objects, and rather focuses on objects, and
    > behaviour only, with an elegant syntax like ruby has (but less complex
    > as a whole)


    I wonder if Io fits the bill?


    --
    James Britt

    www.happycamperstudios.com - Wicked Cool Coding
    www.jamesbritt.com - Playing with Better Toys
    www.ruby-doc.org - Ruby Help & Documentation
    www.rubystuff.com - The Ruby Store for Ruby Stuff
    James Britt, Jun 21, 2008
    #11
  12. James Coglan

    James Coglan Guest

    [Note: parts of this message were removed to make it a legal post.]

    2008/6/21 James Britt <>:

    > Marc Heiler wrote:
    >
    >> I don't know why exactly --only Matz knows-- but IMO the choice is
    >>> somewhat arbitrary because whichever is chosen, class or module, you
    >>> have to take away some of its typical behaviors to have it be
    >>> singletonsomething.
    >>>

    >>
    >> At times I wanted a language that does away with the distinction between
    >> class and module and objects, and rather focuses on objects, and behaviour
    >> only, with an elegant syntax like ruby has (but less complex as a whole)
    >>

    >
    > I wonder if Io fits the bill?



    Possibly JavaScript fits the bill, as at its core it's simply composed of
    Objects and Functions. (JavaScript 'classes' are really just constructor
    functions.)

    I was thinking about the distinction between classes and modules earlier and
    I think it's an important one. Having single-inheritance classes makes sense
    semantically, as class trees are supposed to mirror the problem you're
    solving, and many things can be nicely modelled using a tree of categories.
    Modules are really more about implementing cross-cutting concerns like
    logging, observability or enumerability and it often does not make sense for
    them to be part of the class tree or even to be instantiable. There is no
    way you'd get me to make all my observable types inherit from an Observable
    class -- it makes more sense to mix it in as a module.

    In short, I think both do important (and distinct) jobs, and I'd much rather
    have this than single inheritance without mixins (like Java -- see my
    Observable argument) or all-out multiple inheritance, which doesn't make
    sense semantically. Having a balance of both tools gives you a great deal of
    power to get your design just right. Although you can *implement* class
    inheritance as a special case of module inclusion, that isn't really how I
    want to think when structuring my programs.

    Still, you could give JS.Class a shot, then you've got classes, modules, and
    JavaScript's own object system to play with...

    James
    http://jsclass.jcoglan.com
    James Coglan, Jun 21, 2008
    #12
  13. Marc Heiler wrote:
    >> I don't know why exactly --only Matz knows-- but IMO the choice is
    >> somewhat arbitrary because whichever is chosen, class or module, you
    >> have to take away some of its typical behaviors to have it be
    >> singletonsomething.

    > At times I wanted a language that does away with the distinction between
    > class and module and objects, and rather focuses on objects, and
    > behaviour only, with an elegant syntax like ruby has (but less complex
    > as a whole)


    The prototypical (SCNR) example for such a language would be Self (and
    maybe also the most "pure", maybe even the most pure OO language
    ever), the most modern example would probably be Io and the most
    widespread obviously ECMAScript, but there are others, the most
    well-known ones probably being NewtonScript, Neko and Slate. Maybe
    you'll find one in that list that you like.

    jwm
    Jörg W Mittag, Jun 21, 2008
    #13
  14. Calamitas wrote:
    > On Fri, Jun 20, 2008 at 10:48 AM, James Coglan <> wrote:
    >> What I'm trying to get at is: given that you can't really do anything
    >> 'classy' with a metaclass, it seems they could quite easily be modules
    >> instead, and this makes more sense to me as they are just objects that store
    >> methods. Why do they need to be this specific type of module (i.e. Class)?

    > I don't know why exactly --only Matz knows-- but IMO the choice is
    > somewhat arbitrary because whichever is chosen, class or module, you
    > have to take away some of its typical behaviors to have it be
    > singletonsomething. [...]


    Some time ago, during a discussion about the addition of a
    singleton_class method to Ruby's Core Library, Matz said that he
    didn't want to expose singleton classes that way, because he viewed
    them as a private internal implementation detail of MRI that shouldn't
    be exposed to Ruby code (and force other implementations to copy that
    detail). Not only did he view them as an *internal* implementation
    detail, he actually viewed them as a *bad* implementation detail, one
    that he wished to change. However, he said, he hadn't been able to
    come up with a better idea.

    Since then, he has changed his mind. He has accepted the reality of
    singleton classes, and now his only objection to the addition of a
    singleton_class method is that there is no consensus throughout the
    community on the name of that method: singleton_class, eigenclass,
    metaclass, virtual_class, ...

    So, to cut a long story short: maybe Matz doesn't know either (-:

    jwm
    Jörg W Mittag, Jun 21, 2008
    #14
    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. Stephan Diehl

    question about metaclasses

    Stephan Diehl, Jun 30, 2003, in forum: Python
    Replies:
    2
    Views:
    328
    Stephan Diehl
    Jun 30, 2003
  2. Simon Burton

    metaclasses

    Simon Burton, Jul 28, 2003, in forum: Python
    Replies:
    5
    Views:
    367
    Simon Burton
    Jul 30, 2003
  3. Mike C. Fletcher

    Metaclasses presentation slides available...

    Mike C. Fletcher, Aug 28, 2003, in forum: Python
    Replies:
    3
    Views:
    317
    Alex Martelli
    Aug 29, 2003
  4. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    853
    Mark Rae
    Dec 21, 2006
  5. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,739
    Smokey Grindel
    Dec 2, 2006
Loading...

Share This Page