On Sat, Dec 4, 2010 at 2:56 PM, Peter Vandenabeele
<peter / vandenabeele.com> wrote:
> On Sat, Dec 4, 2010 at 4:37 AM, Tony Arcieri <tony.arcieri / medioh.com> wrote:
>> Is there some overall, grand unifying pattern I'm missing then? Because when
>> I look at Ruby method dispatch it seems a bit like an ad hoc mess
>
> If I understand correctly (and I would welcome corrections), the pattern
> for method lookup is:
>
> Looking up "instance methods" :
>
> * for an object that is not a class (object.class != Class)
[snip]
> * until we reach BasicObject
>
> Looking up "class methods":
>
> * for an object that is a class (object.class == Class)
> * there is always an object.singleton_class
[snip]

There's a much simpler explanation IMHO.

To send a message to an object, (this describes MRI, but other
implementations are probably similar).  The following pseudo code uses
variable names I've made up.

set receiver to the object
set method selector to the symbol representing the method name
set search_klass to receiver -> klass
set method to nil
while method == nil && search_behavior != nil
   unless (method = search_klass.mtab[method_selector])
       search_klass = search_klass.super
   end
end

if method  == nil
  send method_missing(method_selector *args, &block) to receiver #
this is done 'recursively' so the search for method_missing starts
with the receiver's klass.
end

There's no need to treat class method or singleton methods separately.
 The difference is how the klass -> superclass chains are set up.

If an object has a singleton class then the objects klass field points
to the singleton 'class' and the singleton 'class' has its super field
set to point to the original class.

Class methods are just singleton methods on the object which
represents that class, class methods are 'inherited' because the
superclass of the singleton class is set to point to the singleton
class of the class' superclass.

The 'things' pointed to by klass pointers are either:

1) class objects (like Array, Hash, Object etc)  if they are marked by
a flag that they are 'virtual' then they are not returned by methods
like class, superclass, ancestors, etc.  Singleton classes are so
marked this applies to singleton classes of individual objects or
singleton classes of Classes.

or two
2) proxy 'classes' used to represent modules in the inheritance chain,
these are marked as both 'virtual' and 'proxy' IIRC, and point ot the
same mtab as the module they represent.  This allows modules to be
included in multiple klass chains and have changes to the methods of
the module be reflected where ever the module is included, or used to
extend an object.

Module#include inserts a proxy chain starting with a proxy for the
module being included, and followed by proxies for each module
included by that module, etc. before the current 'superclass' of the
class or module being sent #include, again Modules have 'hidden'
superclasses at the implementation level actually these are visible
via the Module#ancestors method.

As an aside, which is probably more apropos the title of this thread.
I don't personally consider singleton_class, eigenclass, and metaclass
to be equivalent terms.

In particular I reserved the term metaclass to be the 'singleton'
class of a class object.  I put singleton in quotes here because,
although MRI uses the singleton class mechanism to implement
metaclasses, metaclasses are 'less' singleton when you consider that
'singleton' methods which are found in the mtab of the object's
singleton class, are not shared by any other object, class methods
which found in the mtab of the metaclass ARE shared in the case where
the class in question has one or more subclasses.

The etymology of the word metaclass is similar to that of metalanguage

meta- (also met- before a vowel or h)
combining form
1 denoting a change of position or condition : metamorphosis | metathesis.
2 denoting position behind, after, or beyond: : metacarpus.
3 denoting something of a higher or second-order kind : metalanguage | metonym.

i.e. the third definition of meta here.

and

metalanguage |metla ng (g)wij|
noun
a form of language or set of terms used for the description or
analysis of another language. Compare with object language (sense 1).
 Logic a system of propositions about propositions.

So as I define it (and as is normal in most OO languages) a metaclass
is a form of class used to describe a class.  A singleton class used
to describe singleton methods of an object is NOT a metaclass but
rather a singleton CLASS for that object, which inherits from the
objects original class, and is hidden from Ruby's reflection methods
because that 'virtual'  bit is set.

IMHO, _why sowed a seed of confusion when he used metaclass in a way
which conflicts with the common definition, in the poignant guide.


> * Note 1: If I understand correctly, for an object that is not
> a class, the singleton_class is not prepared a priori, but
> is generated at the time when it is called.

This is true, although it's really an implementation detail.  I don't
think you can detect this from Ruby without the aid of a C extension
to let you look for a singleton class without having one created
automatically as soon as you ask for it with, say class <<
self;self;end

I suppose I should really turn this into a blog article.

-- 
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Github: http://github.com/rubyredrick
Twitter: @RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale