[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Singleton class's original class

Paul Brannan

9/17/2008 7:23:00 PM

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


11 Answers

ara.t.howard

9/17/2008 7:44:00 PM

0


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

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://codeforp...
--
we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama




Zach Buckholz

9/17/2008 7:50:00 PM

0


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.

TPReal

9/17/2008 9:01:00 PM

0

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

TPReal

9/17/2008 9:07:00 PM

0

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

Jens Wille

9/18/2008 9:56:00 AM

0

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

<http://prometheus.rubyforge.org/ruby-nuggets/classes/Object.html#M...

cheers
jens

Paul Brannan

9/18/2008 2:07:00 PM

0

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

> 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


ara.t.howard

9/18/2008 5:19:00 PM

0


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

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://codeforp...
--
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

9/18/2008 6:23:00 PM

0

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


Jens Wille

9/18/2008 6:46:00 PM

0

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

TPReal

9/18/2008 7:40:00 PM

0

Paul Brannan 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.
--
Posted via http://www.ruby-....