Superclass of eigenclass

Discussion in 'Ruby' started by Danny O cuiv, May 7, 2009.

  1. Danny O cuiv

    Danny O cuiv Guest

    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-talk/248178
    --
    Posted via http://www.ruby-forum.com/.
    Danny O cuiv, May 7, 2009
    #1
    1. Advertising

  2. On Thu, May 7, 2009 at 8:35 AM, Danny O cuiv <> 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]
    Gregory Brown, May 7, 2009
    #2
    1. Advertising

  3. On Thu, May 7, 2009 at 8:35 AM, Danny O cuiv <> 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.denhaven2.com/
    Twitter: http://twitter.com/RickDeNatale
    WWR: http://www.workingwithrails.com/person/9021-rick-denatale
    LinkedIn: http://www.linkedin.com/in/rickdenatale
    Rick DeNatale, May 7, 2009
    #3
  4. On Thu, May 7, 2009 at 11:50 AM, Rick DeNatale <> wrote:
    > On Thu, May 7, 2009 at 8:35 AM, Danny O cuiv <> 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.denhaven2.com/
    Twitter: http://twitter.com/RickDeNatale
    WWR: http://www.workingwithrails.com/person/9021-rick-denatale
    LinkedIn: http://www.linkedin.com/in/rickdenatale
    Rick DeNatale, May 7, 2009
    #4
  5. Danny O cuiv

    Danny O cuiv Guest

    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/.
    Danny O cuiv, May 7, 2009
    #5
  6. On Thu, May 7, 2009 at 1:17 PM, Danny O cuiv <> 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.denhaven2.com/
    Twitter: http://twitter.com/RickDeNatale
    WWR: http://www.workingwithrails.com/person/9021-rick-denatale
    LinkedIn: http://www.linkedin.com/in/rickdenatale
    Rick DeNatale, May 7, 2009
    #6
  7. Danny O cuiv

    Robert Dober Guest

    On Thu, May 7, 2009 at 7:17 PM, Danny O cuiv <> 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.
    Robert Dober, May 7, 2009
    #7
  8. Danny O cuiv

    Danny O cuiv Guest

    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-talk/248178

    (link repeated from my original post).

    Regards,

    Danny.

    --
    Posted via http://www.ruby-forum.com/.
    Danny O cuiv, May 7, 2009
    #8
  9. Danny O cuiv

    Robert Dober Guest

    On Thu, May 7, 2009 at 10:39 PM, Danny O cuiv <> 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, May 8, 2009
    #9
  10. Danny O cuiv

    Robert Dober Guest

    On Fri, May 8, 2009 at 8:45 AM, Robert Dober <> wrote:
    > On Thu, May 7, 2009 at 10:39 PM, Danny O cuiv <> 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
    Robert Dober, May 8, 2009
    #10
  11. Danny O cuiv

    Danny O cuiv Guest

    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-forum.com/.
    Danny O cuiv, May 11, 2009
    #11
  12. Danny O cuiv

    Robert Dober Guest

    On Mon, May 11, 2009 at 2:42 PM, Danny O cuiv <> 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 ;) 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.

    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
    --=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, May 12, 2009
    #12
  13. Danny O cuiv

    Danny O cuiv Guest

    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/.
    Danny O cuiv, May 12, 2009
    #13
  14. Danny O cuiv

    Gary Wright Guest

    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.


    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
    Gary Wright, May 12, 2009
    #14
  15. Danny O cuiv

    Danny O cuiv Guest

    Gary Wright wrote:
    > 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


    Aaaah! The penny finally drops! Thanks a million for this, Gary. I think
    I'd have been banging my head against a brick wall for ages without your
    explanation.

    I'd probably still stand by my earlier assertion that it's a conceptual
    mess, however. It's just that now that I know what the semantics really
    are, I can work with it. Bad naming trips up even very experienced
    people. For example, in RPL, no lesser luminaries than David Flanagan
    and Matz write on page 238 that super "invokes a method with the same
    name as the current one, in the superclass of the current class". Given
    your first point above, it's clear that this is not just misleading,
    it's also Just Plain Wrong (tm).

    That said, for my own purposes, I now have a pretty good picture of the
    semantics (naming snafus and all) and can definitely work with that
    picture. So thanks again.

    Regards,

    Danny


    --
    Posted via http://www.ruby-forum.com/.
    Danny O cuiv, May 12, 2009
    #15
  16. On May 7, 5:35 am, Danny O cuiv <> 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. 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.

    > 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):
    >
    > 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-talk/248178
    > --
    > Posted viahttp://www.ruby-forum.com/.
    David Flanagan, May 13, 2009
    #16
  17. On May 7, 9:21 am, Rick DeNatale <> wrote:
    > On Thu, May 7, 2009 at 11:50 AM, Rick DeNatale <> wrote:
    > > On Thu, May 7, 2009 at 8:35 AM, Danny O cuiv <> 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
    > >>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


    > 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
    David Flanagan, May 13, 2009
    #17
  18. On May 11, 5:42 am, Danny O cuiv <> wrote:
    > 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.

    > Regards,
    >
    > Danny
    >
    > --
    > Posted viahttp://www.ruby-forum.com/.
    David Flanagan, May 13, 2009
    #18
  19. On May 12, 9:29 am, Danny O cuiv <> wrote:
    > Gary Wright wrote:
    > > Confusion comes from:
    > > -- the super keyword uses the method lookup chain, not thesuperclass
    > > chain
    > > -- the ancestor method reports on the method lookup chain, not the
    > > inheritance chain


    I have to disagree with Gary's nomenclature. Inheritance and method
    lookup are basically the same thing, so trying to distinguish "method
    lookup chain" from "inheritance chain" is hard to do. Maybe we can
    say "class hierarchy" when we want to exclude modules as the
    superclass method does and "method inheritance chain" (or something)
    when we want to include modules.

    > Aaaah! The penny finally drops! Thanks a million for this, Gary. I think
    > I'd have been banging my head against a brick wall for ages without your
    > explanation.
    >
    > I'd probably still stand by my earlier assertion that it's a conceptual
    > mess, however. It's just that now that I know what the semantics really
    > are, I can work with it. Bad naming trips up even very experienced
    > people. For example, in RPL, no lesser luminaries than David Flanagan
    > and Matz write on page 238 that super "invokes a method with the same
    > name as the current one, in thesuperclassof the current class".


    You're right. I should have said something like "in the nearest
    ancestor of the current class" or something to that effect, so that
    modules are included. I may also want to update this paragraph to
    point out that a singleton method of an object can chain to a regular
    instance method of the object.

    Thanks for pointing out this error!


    > That said, for my own purposes, I now have a pretty good picture of the
    > semantics (naming snafus and all) and can definitely work with that
    > picture. So thanks again.
    >
    > Regards,
    >
    > Danny
    >
    > --
    > Posted viahttp://www.ruby-forum.com/.
    David Flanagan, May 13, 2009
    #19
  20. Danny O cuiv

    Gary Wright Guest

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

    > On May 12, 9:29 am, Danny O cuiv <> wrote:
    >> Gary Wright wrote:
    >>> Confusion comes from:
    >>> -- the super keyword uses the method lookup chain, not thesuperclass
    >>> chain
    >>> -- the ancestor method reports on the method lookup chain, not the
    >>> inheritance chain

    >
    > I have to disagree with Gary's nomenclature.


    No problem. I just made them up for that post.

    > Inheritance and method
    > lookup are basically the same thing, so trying to distinguish "method
    > lookup chain" from "inheritance chain" is hard to do.


    But since they are only 'basically the same' and not exactly the same
    it is important to distinguish between them. This is more important in
    1.8.X than in 1.9.X since in 1.9.X 'superclass' tracks the method
    lookup chain more closely. In 1.8.X 'superclass' is pretty hard to
    explain when you try to include singleton classes.

    > Maybe we can say "class hierarchy" when we want to exclude modules
    > as the
    > superclass method does and "method inheritance chain" (or something)
    > when we want to include modules.


    I could quibble with those definitions, but my main point was that
    'ancestors' doesn't match the 'superclass chain' (because of modules)
    nor does it always match the 'method lookup chain' (because of
    eigenclasses).

    Gary Wright
    Gary Wright, May 14, 2009
    #20
    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. Evan Klitzke
    Replies:
    0
    Views:
    358
    Evan Klitzke
    Aug 2, 2007
  2. bart van deenen
    Replies:
    6
    Views:
    749
    bart van deenen
    Mar 3, 2009
  3. Trans
    Replies:
    19
    Views:
    191
    Trans
    Mar 15, 2006
  4. Matt Todd

    Defining Eigenclass

    Matt Todd, Aug 11, 2006, in forum: Ruby
    Replies:
    20
    Views:
    343
    Logan Capaldo
    Aug 13, 2006
  5. Paolo Nusco Perrotta

    Superclass of eigenclass in 1.8.6

    Paolo Nusco Perrotta, Apr 16, 2007, in forum: Ruby
    Replies:
    0
    Views:
    96
    Paolo Nusco Perrotta
    Apr 16, 2007
Loading...

Share This Page