From: Christoph Date: 2002-04-19T11:28:03+09:00 Subject: Re: calling a class method in "class << obj" context "Yukihiro Matsumoto" wrote in message news:1019173510.282346.16617.nullmailer@picachu.netlab.jp... > Hi, > > In message "calling a class method in "class << obj" context" > on 02/04/19, Joel VanderWerf writes: > > |Why doesn't the singleton class of a inherit the foo method? > > Fixed in 1.7; should I backport this behavior? It is comes as a very pleasant surprise to me that you considered the previous behavior broken - I thought it was intentional . The ``meta(n) class'' semantics and the ``singleton class'' criteria of the 1.7 branch changed quite a bit since my post [ruby-talk:33789] (check the different outputs of the appended meta-class illustration script). Here is a wild goose chase kind of idea for simplifying the ``meta-picture'' (maybe Rite?) by sub-typing Class and merging Object.meta and Class etc. class Object def meta(n = 1) unless n.zero? class << self; self end.meta(n-1) else self end end def type(n = 1) unless n.zero? type.type(n-1) else type end end end # then Object.meta == Class # but Object.meta(2) == Class.type # and Class > Class.type > Class.type(2) > # etc # - i.e. the type of ``type(n-1)'' Objects of is Class.type(n-1). # Maybe raise exception for Object.meta(n) if n >= 3 ? /Christoph /The output of the appended script two month ago was ---- C_Meta < B_Meta < A_Meta < Object_Meta < Class < Module < Object Class_Meta < Module_Meta < Object_Meta < Class < Module < Object C_Sing({}) << C < B < A < Object Float_Sing(2.718281828) << Float < Numeric < Object "Higher" order Object_Meta_Meta < Class < Module < Object C_Meta_Meta < Class < Module < Object Float_Sing(3.141592654)_Meta < Class < Module < Object Module_Meta_Meta_Meta < Class < Module < Object C_Meta_Meta_Meta < Class < Module < Object Number of Singletons controlled by GC == 0 ---- and changed to (please ignore the failure of the ``beautifier part'') ---- C_Meta < B_Meta < A_Meta < Object_Meta < Class < Module < Object Class_Meta < Module_Meta < Object_Meta < Class < Module < Object #> < C < B < A < Object #> < Float < Numeric < Object "Higher" order # < Class < Module < Object # < Class < Module < Object #>_Meta < Float_Meta < Numeric_Meta < Object_Meta < Class < Module < Object #_Meta < Class_Meta < Module_Meta < Object_Meta < Class < Module < Object #_Meta < Class_Meta < Module_Meta < Object_Meta < Class < Module < Object Number of Singletons controlled by GC == 0 ---- # original script class Class @@to_s = nil @@level = nil attr_reader :inst def superclasses res = [self] tmp = self res.push tmp while tmp = tmp.superclass return res end def each_superclass klass = self yield klass yield klass while klass = klass.superclass self end def level @level || 0 end def singleton?; true end alias :old_to_s :to_s private :old_to_s def to_s if singleton? if level.zero? (old_to_s.sub(/^(#)$/){"_Sing(#{inst})"} else @to_s end else old_to_s end end alias :inspect :to_s protected def __meta super @@to_s = to_s.concat '_Meta' @@level = level + 1 @meta.instance_eval do @to_s = @@to_s @level = @@level end superclass.__meta if superclass if level.nonzero? def self.__meta; @meta end end return @meta end end class Object @@inst = nil class << self def singleton?; false end undef :inst end def meta(level = 1) return self if level.zero? return __meta.meta(level-1) end def singleton_type class << self; self end end protected def __meta @meta = singleton_type @@inst = self @meta.instance_eval do @inst = @@inst end @meta end end class A; end class B < A; end class C < B def initialize num @num = num end def inspect; @num.inspect end alias :to_s :inspect end def class_chain klass unless klass.level.zero? && klass.singleton? puts klass.superclasses.join(" < ") else res = klass.superclasses puts res.shift.to_s.concat(" << ").concat(res.join(" < ")) end end # Examples class_chain C.meta class_chain Class.meta class_chain C.new({}).meta class_chain Math::E.meta puts "\n\"Higher\" order\n\n" class_chain Object.meta(2) class_chain C.meta(2) class_chain Math::PI.meta(2) class_chain Module.meta(3) class_chain C.meta(3) n = 0 ObjectSpace.each_object(Class) do |klass| klass n+=1 if klass.singleton? end puts "\nNumber of Singletons controlled by GC == #{n}"