[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Superclass of eigenclass

Danny O cuiv

5/7/2009 12:35:00 PM

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):

irb> greeting = "hello"
=> "hello"
irb> greeting.eigenclass
=> #<Class:#<String:0xb7cf5a14>>
irb> 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-t...
--
Posted via http://www.ruby-....

31 Answers

Gregory Brown

5/7/2009 1:25:00 PM

0

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."
>
> 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]

Rick DeNatale

5/7/2009 3:50:00 PM

0

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.

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.

--
Rick DeNatale

Blog: http://talklikeaduck.denh...
Twitter: http://twitter.com/Ri...
WWR: http://www.workingwithrails.com/person/9021-ric...
LinkedIn: http://www.linkedin.com/in/ri...

Rick DeNatale

5/7/2009 4:22:00 PM

0

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.

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


--
Rick DeNatale

Blog: http://talklikeaduck.denh...
Twitter: http://twitter.com/Ri...
WWR: http://www.workingwithrails.com/person/9021-ric...
LinkedIn: http://www.linkedin.com/in/ri...

Danny O cuiv

5/7/2009 5:18:00 PM

0

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-....

Rick DeNatale

5/7/2009 6:26:00 PM

0

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

--
Rick DeNatale

Blog: http://talklikeaduck.denh...
Twitter: http://twitter.com/Ri...
WWR: http://www.workingwithrails.com/person/9021-ric...
LinkedIn: http://www.linkedin.com/in/ri...

Robert Dober

5/7/2009 6:28:00 PM

0

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.)
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.

Danny O cuiv

5/7/2009 8:39:00 PM

0

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:

irb> a.instance_of? s
=> false
irb> 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-t...

(link repeated from my original post).

Regards,

Danny.

--
Posted via http://www.ruby-....

Robert Dober

5/8/2009 6:46:00 AM

0

On Thu, May 7, 2009 at 10:39 PM, Danny O cuiv <danny.ocuiv@gmail.com> wrote=
:
> Rick, Robert,
It seems that language is very important :) 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 ;) 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
--=20
Si tu veux construire un bateau ...
Ne rassemble pas des hommes pour aller chercher du bois, pr=E9parer des
outils, r=E9partir les t=E2ches, all=E9ger le travail=85 mais enseigne aux
gens la nostalgie de l=92infini de la mer.

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

--
Antoine de Saint-Exup=E9ry

Robert Dober

5/8/2009 6:47:00 AM

0

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,
Sorry: occasionally complained

Danny O cuiv

5/11/2009 12:42:00 PM

0

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 ;) 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-....