Hello,
is there a way to get an object, if only its object-specific class is
given? For instance, given
c = class << Hash[:a, 5]
def mult(x)
self[:a] * x
end
self
end
can I retrieve the hash object via evaluation of c?
Regards
Thomas
Hello,
is there a way to get an object, if only its object-specific class is
given? For instance, given
c = class << Hash[:a, 5]
def mult(x)
self[:a] * x
end
self
end
can I retrieve the hash object via evaluation of c?
Regards
Thomas
On Sun, 11 Mar 2007, Thomas H. wrote:
end
can I retrieve the hash object via evaluation of c?
harp:~ > cat a.rb
c = class << Hash[:a, 5]
def mult(x)
self[:a] * x
end
self
end
p c.instance_eval{ self }
harp:~ > ruby a.rb
#<Class:#Hash:0xb75cfd18>
if you are doing much of this sort of thing check out the prototype lib
harp:~ > cat a.rb
require ‘rubygems’
require ‘prototype’
c = Object.prototype(Hash) do
def mult(x)
self[:a] * x
end
def initialize
self[:a] = 5
end
end
p c
harp:~ > ruby a.rb
{:a=>5}
-a
[email protected] wrote/schrieb
[email protected]:
p c.instance_eval{ self }
Thanks a lot.
if you are doing much of this sort of thing check out the prototype lib
I’ll have a look, thanks.
Regards
Thomas
Trans schrieb:
On Sun, 11 Mar 2007, Thomas H. wrote:
is there a way to get an object, if only its object-specific class is
given?I thought we wanted the result to be #Hash:0xb75cfd18?
Tom, I thought so, too, but I didn’t want to show my solution before
there’s a demand for it
Regards,
Pit
On Mar 11, 10:23 am, [email protected] wrote:
self
endp c.instance_eval{ self }
harp:~ > ruby a.rb
#<Class:#Hash:0xb75cfd18>
I thought we wanted the result to be #Hash:0xb75cfd18?
T.
On 3/13/07, Trans [email protected] wrote:
hought we wanted the result to be #Hash:0xb75cfd18?
rick@frodo:/public/rubyscripts$ ruby object_from_sc.rb
#<Class:#Hash:0xb7df1774>
{:a=>5}
oXb7df1774
And here’s how:
rick@frodo:/public/rubyscripts$ cat object_from_sc.rb
with a standard
the integer value
This method
def hex_oid(obj)
“oX#{(obj.object_id*2 & 0xffffffff).to_s(16)}”
end
c2 = class << {:a => 5}
def mult(x)
self[:a] * x
end
self
end
p c2
ObjectSpace.each_object(c2) {|o| p o; puts hex_oid(o)}
–
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/
Rick DeNatale schrieb:
ObjectSpace.each_object(c2) {|o| p o}
Yeah Rick, this is what I came up with at first, too. But I didn’t like
that it examines each Ruby object. Here’s another solution, much
uglier but also faster:
def instance_of_singleton_class_1(sc)
ObjectSpace.each_object(sc) do |obj|
return obj
end
end
def instance_of_singleton_class_2(sc)
obj = nil
sc.class_eval do
if instance_methods(false).include?(“singleton_method_added”)
org = instance_method(“singleton_method_added”)
remove_method(“singleton_method_added”)
end
define_method(“singleton_method_added”) do |m|
obj = self
end
remove_method(“singleton_method_added”)
define_method(“singleton_method_added”, org) if org
end
obj
end
Test that they both work the same:
sc = class << {:a => 5}; self; end
p instance_of_singleton_class_1(sc) # => {:a=>5}
p instance_of_singleton_class_2(sc) # => {:a=>5}
And the benchmark:
require “benchmark”
Benchmark.bmbm do |bm|
bm.report “ObjectSpace” do
1000.times do instance_of_singleton_class_1(sc) end
end
bm.report “singleton_method_added” do
1000.times do instance_of_singleton_class_2(sc) end
end
end
yields:
Rehearsal ----------------------------------------------------------
ObjectSpace 3.109000 0.000000 3.109000 ( 3.188000)
singleton_method_added 0.266000 0.000000 0.266000 ( 0.265000)
------------------------------------------------- total: 3.375000sec
user system total real
ObjectSpace 3.016000 0.000000 3.016000 ( 3.032000)
singleton_method_added 0.266000 0.000000 0.266000 ( 0.266000)
Regards,
Pit
By the way.
I was a little concerned that having just a reference to a singleton
class without a reference to its single instance might not protect
that instance from being GCed.
I took a quick look through the ruby1.8 source and it looks like
singleton class objects have a hidden instance variable named
attached which refers to the instance. This is what it uses to
compute it’s string representation for example.
I don’t think that theres any way to get at that through Ruby however,
for example instance_variable_get(:“attached”) complains that
attached is not a legal instance variable name.
So I guess you could write a C extension which accessed that hidden
variable, but in pure Ruby scanning using ObjectSpace.each_object
works albeit potentially less efficiently.
–
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/
IPMS/USA Region 12 Coordinator
http://ipmsr12.denhaven2.com/
Visit the Project Mercury Wiki Site
http://www.mercuryspacecraft.com/
Trans schrieb:
I imagine ObjectSpace._id2ref and parsing inspect would work.
Too easy, Tom, much too easy Yes, this should work, too, of course.
The only gotchas are that you should make sure that the original #to_s
method is used, and you’d have to add a special case for singleton
classes of modules:
p class << Module; self; end # => #Class:Module
Regards,
Pit
On Mar 13, 11:38 am, Pit C. [email protected] wrote:
return obj define_method("singleton_method_added") do |m|
sc = class << {:a => 5}; self; end
1000.times do instance_of_singleton_class_1(sc) end
singleton_method_added 0.266000 0.000000 0.266000 ( 0.265000)
------------------------------------------------- total: 3.375000secuser system total real
ObjectSpace 3.016000 0.000000 3.016000 ( 3.032000)
singleton_method_added 0.266000 0.000000 0.266000 ( 0.266000)
I imagine ObjectSpace._id2ref and parsing inspect would work.
T.
Pit C. schrieb:
The only gotchas are that you should make sure that the original #to_s
method is used, and you’d have to add a special case for singleton
classes of modules:p class << Module; self; end # => #Class:Module
Tom, sorry for the noise, but you can create pathological situations
where you can’t get at the module via its name:
obj = M = Module.new
obj.to_s
Object.class_eval do
remove_const “M”
end
p class << obj; self; end # => #Class:M
p Object.const_get(“M”) rescue p $! # => #<NameError: M>
Maybe someone doing this deserves some troubles…
Regards,
Pit
On Mar 13, 1:56 pm, “Rick DeNatale” [email protected] wrote:
static VALUE singleton_instance(VALUE obj)
rb_define_method(rb_cClass, “singleton_instance”, singleton_instance, 0);end
end
10000.times do instance_of_singleton_class_1(sc) end
many interations as Trans did, 10000 vs. 1000, the primitive is on the
order of two orders of magnitude faster than either of the other
approaches.
Actually, you mean Pit. He did the benchmarks. This is definitely the
way to do it right though. I would submit this to ruby-core mailing
list and see how it takes over there.
T.
def instance_of_singleton_class_2(sc)
not only is this method faster but it works in a situation where the
ObjectSpace does not. Consider this rspec test pasted in from a personal
introspection lib. It will work with this method but not with the
ObjectSpace:
def singleton
class<<self;self;end
end
def singleton_ancestors
result = []
return result unless pointer = singleton_parent
result << self
begin
result << pointer
end while pointer = pointer.singleton_parent
result
end
it "should get singletons back in the correct order" do
parent = ""
a = parent.singleton
b = a.singleton
c = b.singleton
d = c.singleton
e = d.singleton
f = e.singleton
f.singleton_ancestors.should == [ f, e, d, c, b, a, parent ]
end
On 3/13/07, Trans [email protected] wrote:
Two approaches with a benchmark.
And as I surmised, there’s a really quick way to do this with a
relatively simple extension (at least for ruby1.8, I haven’t looked at
this on 1.9).
rick@frodo:/public/rubyscripts/getsinginst$ cat get_sing_inst.c
#include “ruby.h”
static VALUE singleton_instance(VALUE obj)
{
if (BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) {
return rb_iv_get(obj, “attached”);
}
rb_raise(rb_eTypeError, “not a singleton class”);
}
void Init_get_sing_inst()
{
rb_define_method(rb_cClass, “singleton_instance”, singleton_instance,
0);
}
rick@frodo:/public/rubyscripts/getsinginst$ cat gsi.rb
require ‘get_sing_inst’
h = {:a => 1}
sc = class << h
def foo
end
self
end
p sc.singleton_instance
p sc.singleton_instance.object_id == h.object_id
def instance_of_singleton_class_1(sc)
ObjectSpace.each_object(sc) do |obj|
return obj
end
end
def instance_of_singleton_class_2(sc)
obj = nil
sc.class_eval do
if instance_methods(false).include?(“singleton_method_added”)
org = instance_method(“singleton_method_added”)
remove_method(“singleton_method_added”)
end
define_method(“singleton_method_added”) do |m|
obj = self
end
remove_method(“singleton_method_added”)
define_method(“singleton_method_added”, org) if org
end
obj
end
require “benchmark”
Benchmark.bmbm do |bm|
bm.report “ObjectSpace” do
10000.times do instance_of_singleton_class_1(sc) end
end
bm.report “singleton_method_added” do
10000.times do instance_of_singleton_class_2(sc) end
end
bm.report “primitive” do
10000.times do sc.singleton_instance end
end
end
And now for the benchmark results, note that I’m doing 10 times as
many interations as Trans did, 10000 vs. 1000, the primitive is on the
order of two orders of magnitude faster than either of the other
approaches.
rick@frodo:/public/rubyscripts/getsinginst$ ruby gsi.rb
{:a=>1}
true
Rehearsal ----------------------------------------------------------
ObjectSpace 3.270000 0.100000 3.370000 ( 3.469175)
singleton_method_added 4.450000 0.110000 4.560000 ( 4.580452)
primitive 0.040000 0.000000 0.040000 ( 0.046098)
------------------------------------------------- total: 7.970000sec
user system total real
ObjectSpace 2.300000 0.050000 2.350000 ( 2.352730)
singleton_method_added 4.430000 0.070000 4.500000 ( 4.510719)
primitive 0.040000 0.000000 0.040000 ( 0.037970)
–
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/
No, this was deliberate. Maybe it was a mistake… My singleton_parent
retrieves attached, but I was saying Pit’s
instance_of_singleton_class_2 method works as a replacement for this
where as ObjectSpace does not. Here, I’ve refactored the
instance_of_singleton_class_2 into a singleton_parent method for you:
def singleton_parent
# instance_variable_get( ‘attached’ )
return nil unless is_a? Class
obj = nil
class_eval do
if instance_methods( false ).include?( “singleton_method_added” )
org = instance_method( :singleton_method_added )
remove_method( :singleton_method_added )
end
define_method( :singleton_method_added ) do |m|
obj = self
end
remove_method( :singleton_method_added )
define_method( :singleton_method_added, org) if org
end
obj
end
I think you forgot to define singleton_parent.
David
Hi –
On Fri, 21 Mar 2008, Rob Pitt wrote:
def singleton_ancestors
result = []
return result unless pointer = singleton_parent
I think you forgot to define singleton_parent.
David
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.
Sponsor our Newsletter | Privacy Policy | Terms of Service | Remote Ruby Jobs