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.