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.
2008/6/19 James C. [email protected]:
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
irb(main):005:0> x === o
=> true
=> [#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?
On 20.06.2008 00:27, James C. 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 K. 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
On Thu, Jun 19, 2008 at 3:23 PM, James C. [email protected]
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
2008/6/20 Sebastian H. [email protected]:
Robert K. 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
2008/6/20 Calamitas [email protected]:
Well, I don’t think instantiability by itself is a requirement for a
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)?
On Fri, Jun 20, 2008 at 10:48 AM, James C. [email protected]
wrote:
irb(main):012:0> s.class.superclass
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
Marc H. 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 B.
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
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)
Marc H. 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
Calamitas wrote:
On Fri, Jun 20, 2008 at 10:48 AM, James C. [email protected] 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
2008/6/21 James B. [email protected]:
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
Hi –
On Sun, 22 Jun 2008, Jörg W Mittag wrote:
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.
I may not have been in on that particular discussion but I always had
the impression that Matz emphasized that the main point was that Ruby
objects can adapt away from their original classes, and that the use
of singleton classes was one way to implement this but was not,
itself, the goal. I don’t think they can be regarded as an
implementation detail, though, or some kind of undocumented necessary
evil, since the class keyword was always engineered to accept “<<
object”. My impression was that Matz reserved the right to move away
from the class-based implementation (there was one discussion about
the possibility of a new “class-like” object), but didn’t necessarily
condemn the current way it’s done.
I’ve always thought of the availability of a class interface to the
object’s individual behavior as elegant and economical. It also makes
it relatively easy to explain singleton/individual behavior, since
it’s cut from the same cloth, so to speak, as the way objects work
anyway.
David