Singleton class's original class

Given a singleton class:

  irb(main):001:0> class Foo
  irb(main):002:1> def self.singleton_class
  irb(main):003:2> return class << self; self; end
  irb(main):004:2> end
  irb(main):005:1> end
  => nil
  irb(main):006:0> sc = Foo.singleton_class
  => #<Class:Foo>

How can I get class that the singleton class is a singleton class of?

(and is there a name for this?)

  class << sc
    def un_singleton_class
      # ?
    end
  end

  sc.un_singleton_class #=> Foo

I know only of the brute-force solution:

  irb(main):011:0> sc = Foo.singleton_class
  => #<Class:Foo>
  irb(main):012:0> class Class; def singleton_class; class << self; self; end; end; end
  => nil
  irb(main):013:0> ObjectSpace.each_object(Class) { |c| break c if c.singleton_class == sc }
  => Foo

But I was hoping I had overlooked something.

Paul

it might not be a class... but will this work?

cfp:~ > cat a.rb
class Object
   def singleton_class &block
     sc =
       class << self
         self
       end

     unless sc.respond_to?(:parent)
       parent_id = self.object_id #Module === self ? self : self.class
       sc.instance_eval "def parent() ObjectSpace._id2ref(#{ parent_id }) end"
     end

     block ? sc.module_eval(&block) : sc
   end
end

p File.singleton_class.parent
p Array.new.singleton_class.parent
p Hash.new.singleton_class.parent

p Hash.new.singleton_class{ parent }
p Hash.singleton_class{ parent }

options = { :key => :value }

options.singleton_class do
   def getopt opt
     fetch(opt.to_s.to_sym) rescue fetch(opt.to_s)
   end
end

p options.getopt(:key)

cfp:~ > ruby a.rb
File

{}
Hash
:value

a @ http://codeforpeople.com/

···

On Sep 17, 2008, at 1:23 PM, Paul Brannan wrote:

Given a singleton class:

irb(main):001:0> class Foo
irb(main):002:1> def self.singleton_class
irb(main):003:2> return class << self; self; end
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> sc = Foo.singleton_class
=> #<Class:Foo>

How can I get class that the singleton class is a singleton class of?

(and is there a name for this?)

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

Paul Brannan wrote:

How can I get class that the singleton class is a singleton class of?

In general, an eigenclass (or singleton class) can be an eigenclass of
anything, and not only of a class. It can be like this:
class<<"asd";self;end.

  irb(main):013:0> ObjectSpace.each_object(Class) { |c| break c if
c.singleton_class == sc }
  => Foo

Why complicate?

a=anything
ec=class<<a;self;end
a_=nil
ObjectSpace.each_object(ec){|aa| a_=aa}
a.equal?(a_) #=> true

The object space will call the block only once.

TPR.

···

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

I have a script that queries servers in our environment to assist with
patch-levels etc... I am having an issue and need to backtrace which
class called my class.

What I currently have
print "\nCollectData Failed 2: in needDate != yes & package == none
#{hostName}\n"

What I would like to have
print "\nCollectData Failed 2: in needDate != yes & package == none
#{hostName}, called from #{callingClass}\n"

collectdata.rb:class CollectData
collectdata.rb: print "\nCollectData
Failed 1: in package != none and needDate == no #{hostName}\n"
collectdata.rb: print "\nCollectData
Failed 2: in needDate != yes & package == none #{hostName}\n"
collectdata.rb: print "\nCollectData
Failed 3: in needDate == yes #{hostName}\n"
collectdata.rb: print "\nCollectData
Failed: #{hostName}\n"
rpmlist.rb: rpmInfo =
CollectData.new(hostName)
rpmmysql.rb: rpmInfo2 =
CollectData.new(hostName,package.signature)

This message is private and confidential. If you have received it in error, please notify the sender and remove it from your system.

Thomas B. [2008-09-17 23:07]:

Why complicate?

a=anything
ec=class<<a;self;end
a_=nil
ObjectSpace.each_object(ec){|aa| a_=aa}
a.equal?(a_) #=> true

thanks, absorbed :wink:

<http://prometheus.rubyforge.org/ruby-nuggets/classes/Object.html#M000085&gt;

cheers
jens

it might not be a class... but will this work?

It would, except that calling #singleton_class isn't the only way to get
a singleton class. :frowning:

    unless sc.respond_to?(:parent)
      parent_id = self.object_id #Module === self ? self : self.class
      sc.instance_eval "def parent() ObjectSpace._id2ref(#{ parent_id })
end"
    end

Does doing this allow a class to be garbage-collected but allow its
singleton class to stick around?

Probably better to use define_method with a block in this case.

Paul

···

On Thu, Sep 18, 2008 at 04:43:40AM +0900, ara.t.howard wrote:

I like your idea, though consider:

irb(main):001:0> class Base; end
=> nil
irb(main):002:0> class Derived < Base; end
=> nil
irb(main):003:0> sc = class << Derived; self; end
=> #<Class:Derived>
irb(main):004:0> ObjectSpace.each_object(sc) { |c| p c }
Derived
=> 1
irb(main):005:0> sc = class << Base; self; end
=> #<Class:Base>
irb(main):006:0> ObjectSpace.each_object(sc) { |c| p c }
Derived
Base
=> 2

···

On Thu, Sep 18, 2008 at 06:07:29AM +0900, Thomas B. wrote:

Why complicate?

a=anything
ec=class<<a;self;end
a_=nil
ObjectSpace.each_object(ec){|aa| a_=aa}
a.equal?(a_) #=> true

Zach Buckholz wrote:

I have a script that queries servers in our environment to assist with
patch-levels etc... I am having an issue and need to backtrace which
class called my class.

What I currently have
print "\nCollectData Failed 2: in needDate != yes & package == none
#{hostName}\n"

What I would like to have
print "\nCollectData Failed 2: in needDate != yes & package == none
#{hostName}, called from #{callingClass}\n"

If I understand correctly what you want, try using the command +caller+
to get what you want. It returns an array with current stack trace.

TPR.

···

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

it might not be a class... but will this work?

It would, except that calling #singleton_class isn't the only way to get
a singleton class. :frowning:

yup - i was afraid you'd say that...

   unless sc.respond_to?(:parent)
     parent_id = self.object_id #Module === self ? self : self.class
     sc.instance_eval "def parent() ObjectSpace._id2ref(#{ parent_id })
end"
   end

Does doing this allow a class to be garbage-collected but allow its
singleton class to stick around?

yes. you don't have to worry about the object being stale when this is called since the singleton class if owned by the object it's looking up by id

Probably better to use define_method with a block in this case.

i was worried about the gc. also you use define_method you have to get into the singleton class of a singleton class - which starts to get yucky. 'def' works at the instance scope so my approach seemed safer and simpler. but i think define_method could be made to work...

Paul

cheers.

a @ http://codeforpeople.com/

···

On Sep 18, 2008, at 8:07 AM, Paul Brannan wrote:

On Thu, Sep 18, 2008 at 04:43:40AM +0900, ara.t.howard wrote:

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

Paul Brannan [2008-09-18 20:23]:

Why complicate?

a=anything
ec=class<<a;self;end
a_=nil
ObjectSpace.each_object(ec){|aa| a_=aa}
a.equal?(a_) #=> true

I like your idea, though consider:

irb(main):001:0> class Base; end
=> nil
irb(main):002:0> class Derived < Base; end
=> nil
irb(main):003:0> sc = class << Derived; self; end
=> #<Class:Derived>
irb(main):004:0> ObjectSpace.each_object(sc) { |c| p c }
Derived
=> 1
irb(main):005:0> sc = class << Base; self; end
=> #<Class:Base>
irb(main):006:0> ObjectSpace.each_object(sc) { |c| p c }
Derived
Base
=> 2

good catch! but this should work then:

irb(main):006:0> ObjectSpace.each_object(sc) { |c| p c if
sc.equal?(class << c; self; end) }
Base
=> 2

i'll update my implementation in ruby-nuggets tomorrow (moving the
check that i'm doing anyway inside the loop; thanks).

cheers
jens

···

On Thu, Sep 18, 2008 at 06:07:29AM +0900, Thomas B. wrote:

Paul Brannan wrote:

Why complicate?

a=anything
ec=class<<a;self;end
a_=nil
ObjectSpace.each_object(ec){|aa| a_=aa}
a.equal?(a_) #=> true

irb(main):006:0> ObjectSpace.each_object(sc) { |c| p c }
Derived
Base
=> 2

You're right. I was thinking about "regular" object's eigenclasses and
not eigenclasses of classes, and with them I think my solution will
work. My mistake.

But now I finally understand the remark I read somewhere and ignored,
because I didn't think it was important. It said that the "method
lookup" for classes includes eigenclasses of their ancestors.

Now I'm wondering if it is possible to construct such an object that
belong to a foreign eigenclass and not be a class itself. In other
words, how to make my code fail even though a is not a Class. Any ideas?

TPR.

···

On Thu, Sep 18, 2008 at 06:07:29AM +0900, Thomas B. wrote:

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

Thomas B. [2008-09-18 21:39]:

Now I'm wondering if it is possible to construct such an object
that belong to a foreign eigenclass and not be a class itself. In
other words, how to make my code fail even though a is not a
Class. Any ideas?

not sure what you mean by that. but it fails for the singleton
classes of objects like true, false, and nil (TrueClass, FalseClass,
and NilClass resp.), which can safely be special-cased. here's the
updated implementation:

# strictly speaking it belongs under Class,
# but i like to keep things together in this case
class Object

  def singleton_object
    [true, false, nil].each { |obj|
      return obj if self.equal?(obj.singleton_class)
    }

    # raises TypeError if neither class nor module
    ObjectSpace.each_object(self) { |obj|
      return obj if self.equal?(obj.singleton_class)
    }

    # if we got here it can't be a singleton class
    # or its singleton object doesn't exist anymore
    raise TypeError
  rescue TypeError
    raise TypeError, 'not a singleton class'
  end

end

cheers
jens