Superclass of eigenclass

On page 261 of The Ruby Programming Language, they state:

"Class objects are special: they have superclasses. The eigenclasses of
class objects are also special: they have superclasses, too. The
eigenclass of an ordinary object stands alone and has no superclass."

This last sentence has me puzzled. The only possible interpretations
that I can imagine would be that calling superclass on the eigenclass of
an ordinary object would result in either (a) a method not found or (b)
the value nil being returned. However, neither of these is the case.

Adding the usual eigenclass method to class Object, we then get in irb
(ruby 1.8.7 on Mac OS X):

greeting = "hello"

=> "hello"

greeting.eigenclass

=> #<Class:#<String:0xb7cf5a14>>

greeting.eigenclass.superclass

=> #<Class:String>

I interpret #<Class:#<String:0xb7cf5a14>> as "a class object for the
string object at 0xb7cf5a14".
I interpret #<Class:String> as "a class object for class String".

This seems reasonable but conflicts with the description given in TRPL
at the top. Any ideas?

Danny.

P.S. In my searches before posting I came across the following that
no-one replied to. It seems that there are variations on the behaviour.

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

···

--
Posted via http://www.ruby-forum.com/\.

On page 261 of The Ruby Programming Language, they state:

"Class objects are special: they have superclasses. The eigenclasses of
class objects are also special: they have superclasses, too. The
eigenclass of an ordinary object stands alone and has no superclass."

This last sentence has me puzzled. The only possible interpretations
that I can imagine would be that calling superclass on the eigenclass of
an ordinary object would result in either (a) a method not found or (b)
the value nil being returned. However, neither of these is the case.

Not exactly an answer to your question, but here are some thoughts.

class A
  p ancestors
end

[A, Object, Kernel]

class A
  f = class << self; self; end
  p f.ancestors
end

[Class, Module, Object, Kernel]

a = "a"

=> "a"

k = class << a; self; end

=> #<Class:#<String:0x25ad14>>

k.ancestors

=> [String, Enumerable, Comparable, Object, Kernel]

···

On Thu, May 7, 2009 at 8:35 AM, Danny O cuiv <danny.ocuiv@gmail.com> wrote:

I'm pretty sure that this is a typo.

Eigenclasses of ordinary objects certainly do have superclasses,
that's how methods not defined in the singleton class sent to the
ordinary object get resolved.

Two things that the eigenclass of an ordinary object can't have that
and eigenclass of a class (which I for one prefer to call a metaclass)
can have is:

1. A subclass
2. Any instances besides that singleton ordinary object, which is why
you get an exception of you try to send new to such an eigenclass.

I've long maintained that Ruby would be quite a bit clearer if we
cleaned up this singleton vs. eigen vs. meta class thing. The fact
that MRI uses a single flag bit marked singleton for both singleton
classes and metaclasses, an implementation artifact which is pretty
much hidden by the internal implementation of methods like class,
ancestors etc. just tends to confuse people.

But that's just my opinion.

···

On Thu, May 7, 2009 at 8:35 AM, Danny O cuiv <danny.ocuiv@gmail.com> wrote:

On page 261 of The Ruby Programming Language, they state:

"Class objects are special: they have superclasses. The eigenclasses of
class objects are also special: they have superclasses, too. The
eigenclass of an ordinary object stands alone and has no superclass."

--
Rick DeNatale

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

On page 261 of The Ruby Programming Language, they state:

"Class objects are special: they have superclasses. The eigenclasses of
class objects are also special: they have superclasses, too. Theeigenclassof an ordinary object stands alone and has nosuperclass."

The text you quote does not match the behavior of any version of Ruby
I can find--I don't recall what I was thinking when I wrote this.
I'll fix this. The description of how method lookup works (and how
class methods are inherited) is conceptually correct, however.

I think it is best to regard the superclass of an eigenclass as an
implementation-defined construct, and not something you can rely on.
As noted throughout this thread, Ruby has fuzzy boundaries between
implementation and specification. And also, superclass and related
methods play some tricks on you. The link you provide to an earlier
ruby-talk message points out that the superclass of an eigenclass is
one way in 1.8.2 and 1.9.x, and is another way in 1.8.6 and 1.8.7.
My experimentation shows that jruby 1.0 works the way ruby 1.9 does in
this regard.

Let's discuss only Ruby 1.9 for now. In this version, I believe that
if o is an object that is not a class, then:

    o.eigenclass.superclass == o.class

Given this, then the method lookup algorithm for o is simple to
describe. Begin with the eigenclass of o and climb the superclass
chain until the method is found. (Where the superclass chain is not
the same thing that is returned by the superclass method, because the
superclass method skips over modules)

Now suppose that o is the Fixnum class, and let's use ' to designate
an eigenclass: Fixnum', Integer' and so on. In this case, methods are
looked up in this hierarchy:

   Fixnum'->Integer'->Numeric'->Object'->BasicObject'->Class->Module-

Object->Kernel->BasicObject

Notice that the eigenclass of the Comparable module is omitted here.
Fixnum does not inherit class methods from ancestors that are modules.

I believe that method inheritance works the same way in all recent
versions of ruby, but that the observability of the inheritance chain
through eigenclasses varies. Don't try this with Ruby 1.8.6 or Ruby
1.8.7.

···

On May 7, 5:35 am, Danny O cuiv <danny.oc...@gmail.com> wrote:

This last sentence has me puzzled. The only possible interpretations
that I can imagine would be that callingsuperclasson theeigenclassof
an ordinary object would result in either (a) a method not found or (b)
the value nil being returned. However, neither of these is the case.

Adding the usualeigenclassmethod to class Object, we then get in irb
(ruby 1.8.7 on Mac OS X):

> greeting = "hello"
=> "hello"
> greeting.eigenclass
=> #<Class:#<String:0xb7cf5a14>>
> greeting.eigenclass.superclass
=> #<Class:String>

I interpret #<Class:#<String:0xb7cf5a14>> as "a class object for the
string object at 0xb7cf5a14".
I interpret #<Class:String> as "a class object for class String".

This seems reasonable but conflicts with the description given in TRPL
at the top. Any ideas?

Danny.

P.S. In my searches before posting I came across the following that
no-one replied to. It seems that there are variations on the behaviour.

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/248178
--
Posted viahttp://www.ruby-forum.com/.

Just for the record, I just submitted the following erratum report to
the O'Reilly site for the book:

Page 261 2nd Paragraph:
The paragraph says:

"Class objects are special: they have superclasses. The eigenclasses of
class objects are also special: they have superclasses, too. The
eigenclass of an ordinary object stands alone and has no superclass."

Both the eigenclass of a class object and the eigenclass of an
ordinary object have a superclass. If not then sending a message to
an ordinary object would end up invoking method_missing.

I think that the paragraph should read:

"Class objects are special: they can have subclasses. The eigenclasses of
class objects are also special: they can have subclasses, too. The
eigenclass of an ordinary object can have neither a subclass, nor any
other instance except that single ordinary object. If an ordinary
object with an eigenclass is duplicated with the Object#dup method,
the duplicate will not acquire any of it's singleton methods. If it is
cloned with the Object#clone method, the result will get an eigenclass
which is a duplicate of the original objects eigenclass, so that each
eigenclass has but a single instance."

The following ruby code (which behaves identically on Ruby 1.8.6,
1.8.7 and 1.9.1) illustrates the above:

module Kernel
  def eigenclass
    class << self;self;end
  end
end

class TestClass

  def bar
    :bar
  end

  def self.foo
    :foo
  end
end

t = TestClass.new
def t.gorp
  :gorp
end

p t_eigenclass = t.eigenclass # => #<Class:#<TestClass:0x232d0>>
p t_eigenclass.superclass # => #<Class:TestClass>

p t.bar # => :bar
p t.gorp # => :gorp

p t_dup = t.dup
p t_clone = t.clone
p t_clone.respond_to?(:gorp) # => true
p t_clone.eigenclass == t_eigenclass # => false
p t_dup.respond_to?(:gorp) # => false

p t.class.foo # => :foo
p t.eigenclass.foo # => :foo

···

On Thu, May 7, 2009 at 11:50 AM, Rick DeNatale <rick.denatale@gmail.com> wrote:

On Thu, May 7, 2009 at 8:35 AM, Danny O cuiv <danny.ocuiv@gmail.com> wrote:

On page 261 of The Ruby Programming Language, they state:

"Class objects are special: they have superclasses. The eigenclasses of
class objects are also special: they have superclasses, too. The
eigenclass of an ordinary object stands alone and has no superclass."

I'm pretty sure that this is a typo.

--
Rick DeNatale

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

Hi Rick,

I suspect that you're right that the text is incorrect. I doubt that
it's a typo (in the sense of something that was fat-fingered) as the
three sentences, taken together, are consistent in what they express. As
such, it seems mistaken, which makes me curious to know what they were
intending to say.

Your investigation of the issue corresponds with mine. I would, however,
take issue with an aspect of your revised wording, specifically the
following:

The eigenclass of an ordinary object can have neither a subclass,
nor any other instance except that single ordinary object.

The ordinary object is not an instance of the eigenclass. In your
example, the ordinary object is an instance of TestClass, not of any
eigenclass. Indeed, there would be a bootstrapping problem if you
regarded the ordinary object as an instance of the eigenclass. (You can
only have an eigenclass in the context of an existing object, so you
couldn't have created that object in the first place by instantiating
the eigenclass.)

The same issue appears in the following statement:

If it is cloned with the Object#clone method, the result will get an eigenclass
which is a duplicate of the original objects eigenclass, so that each
eigenclass has but a single instance."

Regards,

Danny

···

--
Posted via http://www.ruby-forum.com/\.

>> On page 261 of The Ruby Programming Language, they state:

>> "Class objects are special: they have superclasses. The eigenclasses of
>> class objects are also special: they have superclasses, too. The
>>eigenclassof an ordinary object stands alone and has nosuperclass."

> I'm pretty sure that this is a typo.

Just for the record, I just submitted the following erratum report to
the O'Reilly site for the book:

Rick,

It wasn't a typo, and it correctly describes how method inheritance
works, but it doesn't reflect the reality of the superclass method of
eigenclasses.

Your suggested replacement text won't work as a replacement--the point
of the paragraph in question is to explain method inheritance, not to
get into the nitty gritty about eigenclasses.

Having said that, I should perhaps try to fit some of these eigenclass
details into my next edition, as well as your argument for why the
term "singleton class" makes sense.

    David Flanagan

···

On May 7, 9:21 am, Rick DeNatale <rick.denat...@gmail.com> wrote:

On Thu, May 7, 2009 at 11:50 AM, Rick DeNatale <rick.denat...@gmail.com> wrote:
> On Thu, May 7, 2009 at 8:35 AM, Danny O cuiv <danny.oc...@gmail.com> wrote:

Page 261 2nd Paragraph:
The paragraph says:

"Class objects are special: they have superclasses. The eigenclasses of
class objects are also special: they have superclasses, too. Theeigenclassof an ordinary object stands alone and has nosuperclass."

Both theeigenclassof a class object and theeigenclassof an
ordinary object have asuperclass. If not then sending a message to
an ordinary object would end up invoking method_missing.

I think that the paragraph should read:

"Class objects are special: they can have subclasses. The eigenclasses of
class objects are also special: they can have subclasses, too. Theeigenclassof an ordinary object can have neither a subclass, nor any
other instance except that single ordinary object. If an ordinary
object with aneigenclassis duplicated with the Object#dup method,
the duplicate will not acquire any of it's singleton methods. If it is
cloned with the Object#clone method, the result will get aneigenclass
which is a duplicate of the original objectseigenclass, so that eacheigenclasshas but a single instance."

The following ruby code (which behaves identically on Ruby 1.8.6,
1.8.7 and 1.9.1) illustrates the above:

module Kernel
defeigenclass
class << self;self;end
end
end

class TestClass

def bar
:bar
end

def self.foo
:foo
end
end

t = TestClass.new
def t.gorp
:gorp
end

p t_eigenclass = t.eigenclass# => #<Class:#<TestClass:0x232d0>>
p t_eigenclass.superclass# => #<Class:TestClass>

p t.bar # => :bar
p t.gorp # => :gorp

p t_dup = t.dup
p t_clone = t.clone
p t_clone.respond_to?(:gorp) # => true
p t_clone.eigenclass== t_eigenclass # => false
p t_dup.respond_to?(:gorp) # => false

p t.class.foo # => :foo
p t.eigenclass.foo # => :foo

--
Rick DeNatale

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

The ordinary object is not an instance of the eigenclass. In your
example, the ordinary object is an instance of TestClass, not of any
eigenclass.

Well instance is one of those things which the smoke and mirrors in
MRI makes muddy.

Another example is superclass. One definition is that a is a
superclass of b if the superclass slot of b points to a. This is the
sense that the superclass of a class'es eigenclass is the eigenclass
of the classes superclass.

But if you define superclass as what gets returned by the superclass
method, then MRI obscures the truth:

String.eigenclass # => #<Class:String>
Object.eigenclass # => #<Class:Object>
String.superclass # => Object
String.eigenclass.superclass # => #<Class:Class>

If you go in and look at the implementation, you'll find that the
eigenclass of String has a superclass slot which points to the
eigenclass of Object, but the superclass method implementation skips
past 'singleton' classes, until it gets to <Class:Class>

Now the instance_of? method does the same thing, it skips over
'singleton' classes.

So what I'm really talking about is that a singleton class of an
ordinary object has a singleton instance, which is the only meaning of
singleton class which ever made sense to me.

Indeed, there would be a bootstrapping problem if you
regarded the ordinary object as an instance of the eigenclass. (You can
only have an eigenclass in the context of an existing object, so you
couldn't have created that object in the first place by instantiating
the eigenclass.)

That's only if you tie the notion of instantiation and instance too
closely, I don't see it that way.

···

On Thu, May 7, 2009 at 1:17 PM, Danny O cuiv <danny.ocuiv@gmail.com> wrote:

--
Rick DeNatale

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

I did not read that Rick said anything about instantiating, but for
what I am concerned he sure is right
because of this:

irb(main):006:0> a=Object::new
=> #<Object:0x872e658>
irb(main):007:0> s=class << a; self end
=> #<Class:#<Object:0x872e658>>
irb(main):008:0> a.is_a? s
=> true
irb(main):009:0> s::new
TypeError: can't create instance of singleton class
  from (irb):9:in `new'
  from (irb):9
  from /usr/local/bin/irb:12:in `<main>'

Cheers
R.

···

On Thu, May 7, 2009 at 7:17 PM, Danny O cuiv <danny.ocuiv@gmail.com> wrote:

Hi Rick,

I suspect that you're right that the text is incorrect. I doubt that
it's a typo (in the sense of something that was fat-fingered) as the
three sentences, taken together, are consistent in what they express. As
such, it seems mistaken, which makes me curious to know what they were
intending to say.

Your investigation of the issue corresponds with mine. I would, however,
take issue with an aspect of your revised wording, specifically the
following:

The eigenclass of an ordinary object can have neither a subclass,
nor any other instance except that single ordinary object.

The ordinary object is not an instance of the eigenclass. In your
example, the ordinary object is an instance of TestClass, not of any
eigenclass. Indeed, there would be a bootstrapping problem if you
regarded the ordinary object as an instance of the eigenclass. (You can
only have an eigenclass in the context of an existing object, so you
couldn't have created that object in the first place by instantiating
the eigenclass.)

Rick, Robert,

Thanks for your helpful replies. I have just introduced myself to Ruby
in the last couple of weeks by reading The Ruby Programming Language, so
I'm still trying to pin some concepts. One thing I have found
interesting in looking things up online is that it's not uncommon to
refer to C-level constructs in MRI when discussing language semantics.
(I personally would prefer to restrict myself to what's observable from
sample Ruby code.)

Firstly, Robert, you have used "is_a?" in your example. This tests for
(direct or indirect) conformance. I quibbled with the notion that the
ordinary object was an instance of the eigenclass. The normal usage of
the term "instance" to mean "direct instance" is reflected in the
semantics of Ruby's "instance_of?" method. Using this method, we could
extend your sample code as follows:

a.instance_of? s

=> false

a.instance_of? Object

=> true

This is what I meant, and to me, this is significant. One of my
reference points in reading about Ruby was Smalltalk, which has the
notion of a metaclass. In Smalltalk the concept is clear. (Indeed, the
only reasonable meaning for the term metaclass is "a class whose
instances are classes".) In Ruby, some people contend that eigenclass
and metaclass are synonyms, which seems to me to confuse two distinct
notions. In the interests of conceptual clarity, here's my take on the
two notions. (Feel free to poke holes in this if it's totally
upside-down or otherwise mistaken.)

(a) Eigenclass
Ruby allows for per-instance methods (deliberately avoiding the more
common term as it's overloaded with a well-known pattern). The
conceptual container for these per-instance methods is the object's
eigenclass. The precise implementation of this notion in the reference
notion should be immaterial. What is important is that a decision was
made to reify the notion by providing language syntax to open it up, as
follows:
class << myObject
This allows for dealing with several per-instance methods together. More
to the point, if this syntax was not part of the language, eigenclasses
would be purely an implementation notion and have no correspondence in
Ruby code.

(b) Metaclass
To me, there is only one metaclass in Ruby, namely class Class. (By any
reasonable definition of the term metaclass.) It seems to me mistaken to
equate the terms metaclass and eigenclass. For one thing, every object
in Ruby has an eigenclass (not just class objects). Secondly, even if we
restrict our consideration purely to eigenclasses of class objects,
these don't really qualify as metaclasses either. In Smalltalk, every
class object is a (direct) instance of a metaclass. In Ruby, class
objects are not (direct) instances of any eigenclass; they are all
(direct) instances of class Class.

From this, it would seem to me that the term metaclass should not be
used in Ruby. (Flanagan and Matz possibly agree as they seem to largely
avoid the term in their book).

I would, however, agree with Rick about the muddiness surrounding
superclasses. For example, the example on page 294-295-296 of the book
uses the eigenclass to wrap tracing code around methods. In doing so,
they use a call to super to access the original implementation. Now
super, by the definition on page 238, "invokes a method with the same
name as the current one, in the superclass of the current class". So,
for this to work, the superclass of the eigenclass needs to be the
original class. In other words, let's say we have a class called X, an
instance of that class called x and let's say the eigenclass of x is e.
The method on page 294 will work if the superclass of e is X. (Because
that's where the original implementation is defined.) However, this is
not the case. The superclass of the eigenclass is not the original
class. It is the eigenclass of the original class. Finally, note that in
saying "the superclass of the eigenclass is not the original class", it
would appear that it was at one stage. According to Paolo Nusco
Perrotta, at least some implementations of 1.8.2 and 1.9 had this
behaviour:

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

(link repeated from my original post).

Regards,

Danny.

···

--
Posted via http://www.ruby-forum.com/\.

Rick, Robert,

Thanks again for your replies.

Rick wrote:

If you go in and look at the implementation, you'll find that the
eigenclass of String has a superclass slot which points to the
eigenclass of Object, but the superclass method implementation skips
past 'singleton' classes, until it gets to <Class:Class>

To me, that smacks of being ad hoc and inconsistent. The superclass
method implementation skips past 'singleton' classes, until it gets to
#<Class:Class>. But #<Class:Class> is itself a 'singleton' class, so I
can't see the rationale there. In other words, I can't really grasp what
semantics are being exposed.

Robert wrote:

But in reality singleton classes, yes that is what I prefer :wink: are
very simple because you really never care too much about their
inheritance. The more I work with Ruby the less I care about
inheritance in general.

I would disagree that one would never really care too much about an
eigenclass's inheritance. Example 8-10 on page 294 of the Flanagan/Matz
book details a very nice-looking technique for doing interception. (The
particular example uses the technique to wrap tracing code.) This
technique depends on accessing the original implementation of the method
by calling super in an eigenclass, so the inheritance of the eigenclass
is crucial here.

In attempting to understand why this might work, I have four conflicting
viewpoints. Say I have a class X that I instantiate to get a regular
object x. Say that the eigenclass of x is e. For the interception
technique to work, X needs to be above e in the inheritance hierarchy.

(i) The Flanagan/Matz book says that an eigenclass of a regular object
doesn't have a superclass. (So that e has no superclass.) Clearly this
is incorrect.

(ii) Exploring using the superclass method gives:
e.superclass # => #<Class:X>
e.superclass.superclass # => #<Class:Class>
e.superclass.superclass.superclass # => #<Class:Class>
with the same result for any further calls to superclass. This indicates
that X is not in the inheritance hierarchy of e and consequently the
technique should not work.

(iii) Exploring using the ancestors method gives:
e.ancestors # => [X, Object, Kernel]
This indicates that X is in the inheritance hierarchy of e and
consequently the technique should work.

(iv) Exploring using is_a?
x.is_a? e # => true
This indicates that e is in the inheritance hierarchy of X (i.e. the
opposite of the previous indication) and consequently the technique
should not work.

I'd have to confess that this seems like a conceptual mess to me. I
presume that I'm grasping the wrong end of some stick or other. Can
anyone help point out what that might be?

Regards,

Danny

···

--
Posted via http://www.ruby-forum.com/\.

It seems that language is very important :slight_smile: my English and my
Smalltalk are very far of those of Rick, and I have realized that
indeed he read very much better what you meant.

However, although I agree that those terms are somehow not defined up
to the last detail in Ruby, and I have occasionaly explained about it,
I just wanted to give you a practical example.
It is very good to have some unbiased views on things.

But in reality singleton classes, yes that is what I prefer :wink: are
very simple because you really never care too much about their
inheritance. The more I work with Ruby the less I care about
inheritance in general.

Cheers
Robert

···

On Thu, May 7, 2009 at 10:39 PM, Danny O cuiv <danny.ocuiv@gmail.com> wrote:

Rick, Robert,

--
Si tu veux construire un bateau ...
Ne rassemble pas des hommes pour aller chercher du bois, préparer des
outils, répartir les tâches, alléger le travail… mais enseigne aux
gens la nostalgie de l’infini de la mer.

If you want to build a ship, don’t herd people together to collect
wood and don’t assign them tasks and work, but rather teach them to
long for the endless immensity of the sea.

--
Antoine de Saint-Exupéry

yes but I was talking about the other direction in the inheritance
tree, the super class of a singleton class is very well defined as the
class of the singleton's class object's class. Are we cycling here ;)?

Cheers
Robert

···

On Mon, May 11, 2009 at 2:42 PM, Danny O cuiv <danny.ocuiv@gmail.com> wrote:

Rick, Robert,

Thanks again for your replies.

Rick wrote:

If you go in and look at the implementation, you'll find that the
eigenclass of String has a superclass slot which points to the
eigenclass of Object, but the superclass method implementation skips
past 'singleton' classes, until it gets to <Class:Class>

To me, that smacks of being ad hoc and inconsistent. The superclass
method implementation skips past 'singleton' classes, until it gets to
#<Class:Class>. But #<Class:Class> is itself a 'singleton' class, so I
can't see the rationale there. In other words, I can't really grasp what
semantics are being exposed.

Robert wrote:

But in reality singleton classes, yes that is what I prefer :wink: are
very simple because you really never care too much about their
inheritance. The more I work with Ruby the less I care about
inheritance in general.

I would disagree that one would never really care too much about an
eigenclass's inheritance. Example 8-10 on page 294 of the Flanagan/Matz
book details a very nice-looking technique for doing interception. (The
particular example uses the technique to wrap tracing code.) This
technique depends on accessing the original implementation of the method
by calling super in an eigenclass, so the inheritance of the eigenclass
is crucial here.

--
Si tu veux construire un bateau ...
Ne rassemble pas des hommes pour aller chercher du bois, préparer des
outils, répartir les tâches, alléger le travail… mais enseigne aux
gens la nostalgie de l’infini de la mer.

If you want to build a ship, don’t herd people together to collect
wood and don’t assign them tasks and work, but rather teach them to
long for the endless immensity of the sea.

--
Antoine de Saint-Exupéry

Rick, Robert,

Thanks again for your replies.

Rick wrote:
> If you go in and look at the implementation, you'll find that the
>eigenclassof String has asuperclassslot which points to the
>eigenclassof Object, but thesuperclassmethod implementation skips
> past 'singleton' classes, until it gets to <Class:Class>

To me, that smacks of being ad hoc and inconsistent. Thesuperclass
method implementation skips past 'singleton' classes, until it gets to
#<Class:Class>. But #<Class:Class> is itself a 'singleton' class, so I
can't see the rationale there. In other words, I can't really grasp what
semantics are being exposed.

The implementation details are leaking. No semantics should be read
into this, I think.

I'd have to confess that this seems like a conceptual mess to me. I
presume that I'm grasping the wrong end of some stick or other. Can
anyone help point out what that might be?

It is a conceptual mess. It seems somewhat clearer, however, with
Ruby 1.9.

···

On May 11, 5:42 am, Danny O cuiv <danny.oc...@gmail.com> wrote:

Regards,

Danny

--
Posted viahttp://www.ruby-forum.com/.

Sorry: occasionally complained

···

On Fri, May 8, 2009 at 8:45 AM, Robert Dober <robert.dober@gmail.com> wrote:

On Thu, May 7, 2009 at 10:39 PM, Danny O cuiv <danny.ocuiv@gmail.com> wrote:

However, although I agree that those terms are somehow not defined up
to the last detail in Ruby, and I have occasionaly explained about it,

Robert Dober wrote:

the super class of a singleton class is very well defined as the
class of the singleton's class object's class.

Robert,

I mustn't be making myself clear.
I fully agree with your statement above. Because the language can get a
bit dense, it's probably clearer to adopt a notation (as I did before)
of a class called X, an instance of X called x and the eigenclass of x
called e.

The superclass of e is (as you say) the eigenclass of X (i.e.
#<Class:X>). The superclass of this is the eigenclass of class Class
(i.e. #<Class:Class>). No problem with this whatsoever. I wouldn't go so
far as to say it's well-defined, because it was different in 1.8.2 and
in some versions of 1.9, but that's a separate issue which we can leave
to one side.

However, what is clear from the above is that X is not a superclass of
e. This is a problem for two reasons:

(i) Certain metaprogramming techniques (e.g the one on page 295 or RPL)
involve calling super in an eigenclass method, with the intention of
picking up the implementation of the same method in the original class.
If X is not a superclass of e, this shouldn't work. But it does.

(ii) Calling the ancestors on e gives:
e.ancestors # => [X, Object, Kernel]
So we have X appearing as an ancestor of e, when it is neither a
superclass of e nor an included class in e.

Somebody here must have a better handle on this than me. Please chip in
if you do.

Thanks,

Danny.

···

--
Posted via http://www.ruby-forum.com/\.

Rick, Robert,

Thanks again for your replies.

Rick wrote:

If you go in and look at the implementation, you'll find that the
eigenclassof String has asuperclassslot which points to the
eigenclassof Object, but thesuperclassmethod implementation skips
past 'singleton' classes, until it gets to <Class:Class>

To me, that smacks of being ad hoc and inconsistent. Thesuperclass
method implementation skips past 'singleton' classes, until it gets to
#<Class:Class>. But #<Class:Class> is itself a 'singleton' class, so I
can't see the rationale there. In other words, I can't really grasp what
semantics are being exposed.

The implementation details are leaking. No semantics should be read
into this, I think.

I'd have to confess that this seems like a conceptual mess to me. I
presume that I'm grasping the wrong end of some stick or other. Can
anyone help point out what that might be?

It is a conceptual mess. It seems somewhat clearer, however, with
Ruby 1.9.

I agree completely. In fact, beyond implementation detail, is there any reason that eigenclasses exist in their semi-privileged realm? For example, I've never completely understood why the following shouldn't work:

>> class Test
>> def eigenclass
>> class<<self
>> self
>> end
>> end
>> end
=> nil
>> TestSubEigen = Class.new(Test.new.eigenclass)
TypeError: can't make subclass of virtual class
  from (irb):43:in `initialize'
  from (irb):43:in `new'
  from (irb):43

In fact, it seems like the existence of eigenclasses is, to begin with, an implementation detail. As it turns out, they can be very handy for implementing instance-specific methods, but then isn't that the point of a Prototype inheritance model?

Personally, I would like to see Ruby 2.0 formalize Ruby's prototyping abilities. The semantics of "Test.new" could remain the same and be conceptually identical to "Test.prototype.prototype". That is, eigenclasses would be prototype objects that sit between the object and its parent class object. This would have the added benefit of clearing up the method call chain concept, as it would simply follow the trail of prototypes.

Just ideas...

Cheers,

Josh

···

On May 13, 2009, at 6:10 PM, David Flanagan wrote:

On May 11, 5:42 am, Danny O cuiv <danny.oc...@gmail.com> wrote:

Robert Dober wrote:

However, although I agree that those terms are somehow not defined up
to the last detail in Ruby, and I have occasionaly explained about it,

You mean "complained", right? Yes, it is kind of unfortunate, that we
ended up with this confusion. I would like to point out, however, that
this is basically a historical accident, and not anybody's (certainly
not matz's) fault.

The fundamental problem is that matz has always refused (and still
refuses) to pick a name. And over time he has done that for two
different reasons. Originally, he considered singleton classes to be a
private implementation detail of MRI, and he envisioned that there
would be other implementations that would choose to implement
singleton methods differently. He wanted to have per-object methods,
and he needed something to store them in, so he chose something that
was *already* supported by MRI: a class. Additionally, this meant that
he needed exactly 0 changes to the method resolution algorithm, and
only one single if-condition in the superclass algorithm. *And* he
could reuse that same solution for mixins.

Unfortunately, that supposedly private implementation was leaked to
the programmer, exactly *because* the singleton class is "just a
class". Due to the way class bodies work (namely that they return the
value of the last expression inside the body instead of the class
object, and that self is bound to the class object), you can get
access to the singleton class with the 'class << self; self end' trick
(or its equivalent).

As soon as you can get access to something, you need to name it. And
people did. They named it singleton class, eigenclass, virtual class,
hidden class, metaclass and dozens more ...

Which brings us to the present. *Now* matz refuses to pick a name,
because he doesn't want to ... well, *pick* a name. He wants the
*community* to pick a name, and he will simply approve whatever we
come up with. What it boils down to is that he does *not* consider
himself a "benevolent dictator", but more a "benevolent chairman" who
does not himself make decisions, but rather tries to "milk" a
consensus out of a very diverse group of very opinionated people, just
like a chairman of a senate committee would (well, at least in an
ideal world where neither the members nor the chairman are corrupt or
in any way influenced by lobbyists).

Currently, singleton class, eigenclass and metaclass are still in the
race. I agree that metaclass is wrong, but since it is the name used
by _why the lucky stiff in what is probably one of the best
introductory texts about the more esoteric corners of Ruby's object
system, a lot of Rubyists learn that name, so it is going to stick
with us. Of the other two I prefer eigenclass, both to avoid the
confusion with the singleton pattern and because it nicely fits in
with the already existing usages in mathematics (eigenvalue,
eigenvector, eigenspace, eigenmode, eigenfrequency, eigenstate,
eigenspectrum, eigenfunction, eigendecomposition, eigenproblem) and
computer science (eigenface, eigenratio).

jwm

I think you need to decouple the inheritance relationships (what superclass reveals) from the method lookup chain (what ancestor partially reveals) in order to understand the semantics. Arguably this could all be clearer via some better naming.

Confusion comes from:
-- the super keyword uses the method lookup chain, not the superclass chain
-- the ancestor method reports on the method lookup chain, not the inheritance chain
-- the ancestor method doesn't show eigenclasses, they are implied

···

On May 12, 2009, at 10:38 AM, Danny O cuiv wrote:

However, what is clear from the above is that X is not a superclass of
e. This is a problem for two reasons:

(i) Certain metaprogramming techniques (e.g the one on page 295 or RPL)
involve calling super in an eigenclass method, with the intention of
picking up the implementation of the same method in the original class.
If X is not a superclass of e, this shouldn't work. But it does.

(ii) Calling the ancestors on e gives:
e.ancestors # => [X, Object, Kernel]
So we have X appearing as an ancestor of e, when it is neither a
superclass of e nor an included class in e.

Somebody here must have a better handle on this than me. Please chip in
if you do.

Joshua Ballanco wrote:

In fact, it seems like the existence of eigenclasses is, to begin
with, an implementation detail.

Originally, they were.

As it turns out, they can be very
handy for implementing instance-specific methods,

Exactly. It is my understanding that they were only added as a place
to "stick" per-object methods. MRI already had classes, so why not use
them? If you stick per-object methods in an eigenclass you need
exactly 0 new constructs in the interpreter, 0 changes to method
lookup and just one if-condition in superclass lookup. Plus, you can
also implement mixins the same way. That's a *lot* of leverage for
essentially one line of code.

AFAIK, the fact that they were exposed to the programmer is more of an
accident than a well-designed thought-out language feature.

jwm