On 5/3/05, Ara.T.Howard / noaa.gov <Ara.T.Howard / noaa.gov> wrote:
> On Wed, 4 May 2005, Mark Hubbart wrote:
> 
> > On 5/3/05, Ara.T.Howard <Ara.T.Howard / noaa.gov> wrote:
> >>
> >> thoughts on how to do this
> >>
> >>    class C
> >>      class << self
> >>        p un_metaclass #=> C
> >>      end
> >>    end
> >>
> >> ??
> >
> > heh... I was ahead of you on that one :) in the "inside_metaclass?"
> > thread, my solution returned the instance for the "true" value:
> >
> > http://rubytalk.org/140390
> >
> > class Class
> > def metaclass?
> >   id = inspect[/\A\#<Class:\#<.+?\:0x(.+?)>>\Z/, 1]
> >   ObjectSpace._id2ref(id.to_i(16)/2) if id
> > end
> > end
> >
> > Note that this code is very fragile; it will not work on 1.6.x, and
> > isn't guaranteed to work in the future. It extracts the object_id of
> > the instance from the metaclass' inspect string.
> 
> it doesn't seem to work for me:
> 
>    jib:~/eg/ruby > cat a.rb
> 
>    class Module
>      def instance_class
>        m = %r/^(?:#<Class:)+(.*?)(>+)$/io.match inspect
>        if m
>          klass_name, brackets = m[1], m[2]
>          n = brackets.size - 1
>          klass = const_get klass_name
>          n.times{ klass = class << klass; self; end }
>          klass
>        else
>          superclass
>        end
>      end
>      def metaclass?
>        id = inspect[%r/\A\#<Class:\#<.+?\:0x(.+?)>>\Z/, 1]
>        ObjectSpace._id2ref(id.to_i(16)/2) if id
>      end
>      def both
>        [ instance_class, metaclass? ]
>      end
>    end
> 
>    class C
>      p both
>      class << self
>        p both
>        class << self
>          p both
>          class << self
>            p both
>          end
>        end
>      end
>    end
> 
>    class K < C
>      p both
>      class << self
>        p both
>        class << self
>          p both
>          class << self
>            p both
>          end
>        end
>      end
>    end
> 
>    jib:~/eg/ruby > ruby a.rb
>    [Object, nil]
>    [C, nil]
>    [#<Class:C>, nil]
>    [#<Class:#<Class:C>>, nil]
>    [C, nil]
>    [K, nil]
>    [#<Class:K>, nil]
>    [#<Class:#<Class:K>>, nil]
> 
> did i do something wrong?

Ugh. I hadn't thought about the metaclasses of classes, or the
metaclasses of metaclasses of classes. The code will work for any
non-class object, though, I think.

I'm not sure how to do this. Some ugly hacking might make it work, but
it wouldn't be correct. It can probably only be done correctly with C
or DL. I hated parsing the inspect output anyway, there was something
just *wrong* about that. :)

cheers,
Mark