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

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

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

(and is there a name for this?)

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/

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

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

cheers
jens

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

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 Sep 18, 2008, at 8:07 AM, Paul B. wrote:

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

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…

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/

Paul B. [2008-09-18 20:23]:

=> #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:

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

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

Paul B. wrote:

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

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.