The following is the culmination of a discussion on ruby-talk from a few days ago. Someone asked if there was a way to find the instance of a singleton class if you only had the class. After positing a solution using ObjectSpace.each_object, I then wrote a small extension to get it via the hidden __attached__ instance variable. I was then asked to submit it to ruby-core, although I'm not sure whether it's a problem which needs to be addressed in the core. But just in case here's the discussion. If there's interest, I could come up with a patch for 1.8.5, 1.8.6, and maybe 1.9. On 3/13/07, Trans <transfire / gmail.com> wrote: > > > On Mar 13, 1:56 pm, "Rick DeNatale" <rick.denat... / gmail.com> wrote: > > On 3/13/07, Trans <transf... / gmail.com> 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. > > 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. > > > -- 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/