Singleton class's original class

P

Paul Brannan

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
 
A

ara.t.howard

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

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/
 
Z

Zach Buckholz

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 !=3D yes & package =3D=3D none
#{hostName}\n"

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


collectdata.rb:class CollectData
collectdata.rb: print "\nCollectData
Failed 1: in package !=3D none and needDate =3D=3D no #{hostName}\n"
collectdata.rb: print "\nCollectData
Failed 2: in needDate !=3D yes & package =3D=3D none #{hostName}\n"
collectdata.rb: print "\nCollectData
Failed 3: in needDate =3D=3D yes #{hostName}\n"
collectdata.rb: print "\nCollectData
Failed: #{hostName}\n"
rpmlist.rb: rpmInfo =3D
CollectData.new(hostName)
rpmmysql.rb: rpmInfo2 =3D
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.
 
T

Thomas B.

Zach said:
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.
 
T

Thomas B.

Paul said:
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.
 
P

Paul Brannan

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. :(
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
 
A

ara.t.howard

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

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

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

cheers.

a @ http://codeforpeople.com/
 
P

Paul Brannan

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
 
J

Jens Wille

Paul Brannan [2008-09-18 20:23]:
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
 
T

Thomas B.

Paul said:
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.
 
J

Jens Wille

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,705
Latest member
Stefkari24

Latest Threads

Top