infinite number of singleton_classes

C

Christoph

David said:
You're three-deep here, though. I thought you meant to disallow
two-deep (singleton class of a singleton class). (In my example I'm
assuming that "def self.x" puts x into the singleton class of self,
which is itself the singleton class of obj.)


Sorry for being my confusing self::)
It then becomes a little confusing to call them "classes", since
they're instances of something other than Class. And it raises the
whole subclassing Class problem....

Well that's the whole point they (singleton classes) are classes
but they are also very special kind of classes. For normal objects
you would xpress this kind of relation ship by sub classing.
For example, similar to


---
class Rodent; end
class Mouse < Rodent; end
jerry.instance_of?(Mouse) # true
jerry.instance_of?(Rodent) # false
jerry.kind_of?(Rodent) # true
---

it would be

---
class Klass < Class; end # we also have Klass == class << Class; self end

Jerry = class << self; self end
Jerry.instance_of?(Klass) # true
Jerry.instance_of?(Class) # false
Jerry.kind_of?(Class) # true
----

The sub classing problem isn't all that bad because you could allow
sub classing Class exactly once (during the boot up of the object model).
Being a subclass and singleton of a class at the same time may sound
a bit confusing. On the hand, it also would emphasize the central role
of Object, Class (and possibly Klass) and the normal user would never
notice the difference.


/Christoph
 
A

Ara.T.Howard

You have misunderstood somewhere. Ara was not angry.

His "__i__" and "__you__" were quotes -- the Ruby interpreter
talking to the programmer.

hal is quite right! sorry if the original came out wrong - it's what i get
for posting before coffee i the morning!

cheers.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
A

Ara.T.Howard

Hal Fulton a écrit :

In that quote, Ara *was* angry, not with me, but about the 'p' language.

But here:
----8<---
it would be a shame to take a tool away just because someone hasn't figured out
something indespesible to do with that particular tool __yet__
---8<---

Have I misunderstood something once again?

well - sorta ;-)

i only meant to say that the behaviour is consistent and, although there isno
regular ruby idiom that makes use of it now, there may well be in the future.
if it were inconsistent, but could have a potential use, i'd say take 'em
away. my worry is that taking them away now would, in fact, be inconsistent
and that's what reminded me of perl - which is ripe with inconsistencies-
am i making more sense?

cheers.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
A

Ara.T.Howard

Well, I had something in mind when I wrote this... and it was not "Surely no
one will ever use this feature, then let's remove it". It was something more
subtle.

I may be wrong in my interpretation, but I remember that Matz expected some
freedom of implementation of singleton method mechanism. Present mechanism
is that singleton methods are hold in a singleton class, which happens to be
an object instance of the class Class. But this may change in future version
of ruby. For example, singleton "classes" could not be a class anymore, or
it could even not be a normal object anymore. It could be anything, whatever
please Matz.

this makes a good bit more sense to me - but think matz would need to comment
to consider further.

kind regards.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
N

Nakada, Nobuyoshi

Hi,
I'd rather just see the #inspect bug fixed :)

I rather guess singleton class would not be allowed to copy, from its
definition.


Index: class.c
===================================================================
RCS file: /cvs/ruby/src/ruby/class.c,v
retrieving revision 1.89
diff -U2 -p -r1.89 class.c
--- class.c 4 Mar 2005 06:47:45 -0000 1.89
+++ class.c 16 May 2005 05:35:05 -0000
@@ -106,4 +106,7 @@ rb_class_init_copy(clone, orig)
rb_raise(rb_eTypeError, "already initialized class");
}
+ if (FL_TEST(orig, FL_SINGLETON)) {
+ rb_raise(rb_eTypeError, "can't copy singleton class");
+ }
return rb_mod_init_copy(clone, orig);
}
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: Bug printing classes - Re: infinite number of singleton_classes"

|David A. Black wrote:
|> I'd rather just see the #inspect bug fixed :)
|
|I rather guess singleton class would not be allowed to copy, from its
|definition.

Agreed. Can you commit the patch?

matz.
 
L

Lionel Thiry

(e-mail address removed) a écrit :
this makes a good bit more sense to me - but think matz would need to
comment
to consider further.

When I wrote my initial post, I suppose I took for granted that this was
evident, given the so many discussions about singleton class. And I also took
for granted that if one couldn't grasp my position in the first place, he would
be nice enough to ask me to elaborate. ;)

Cheers.
 
C

Christoph

well - sorta ;-)

i only meant to say that the behaviour is consistent and, although
there is no
regular ruby idiom that makes use of it now, there may well be in the
future.

Actually the behavior is not consistent - assuming the definition
----
public # create meta objects
def m(height =1)
height.zero? ? self : class << self; self end.m(height -1)
end
----

and the natural inheritance assumption, that the class relation

X < Y # true, implies
X.m < Y.m # true
---
you would expect the following method lookup path for a
singleton class of "height" 5
---
class A; end
class B < A; end
b = B.new

b.m(5) <- B.m(4) < A.m(4) < Object.m(4) <
Class.m(3) < Module.m(3) < Object.m(3) <
Class.m(2) < Module.m(2) < Object.m(2) <
Class.m < Module.m < Object.m <
Class < Module < Object < Kernel
---

From a practical point of view this would be rather silly, so Matz bend
the rules, and "benevolently ruled" the following to be true
---
b.m(5) < Class.m < Module.m < Object.m <
Class < Module < Object < Kernel
---

I personally still prefer honest exception raising over a trickery like
this.

/Christoh
 
L

Lionel Thiry

Christoph a écrit :
(e-mail address removed) schrieb:
Actually the behavior is not consistent - assuming the definition
----
public # create meta objects
def m(height =1)
height.zero? ? self : class << self; self end.m(height -1)
end
----

and the natural inheritance assumption, that the class relation

X < Y # true, implies
X.m < Y.m # true
---
you would expect the following method lookup path for a
singleton class of "height" 5
---
class A; end
class B < A; end
b = B.new

b.m(5) <- B.m(4) < A.m(4) < Object.m(4) <
Class.m(3) < Module.m(3) < Object.m(3) <
Class.m(2) < Module.m(2) < Object.m(2) <
Class.m < Module.m < Object.m <
Class < Module < Object < Kernel

What an impressive demonstration.

Let me add more precision to your affirmation:
b.m(5) < B.m(4) # => nil
B.m(4) < A.m(4) # => nil
A.m(4) < Object.m(4) # => nil
Object.m(4) < Class.m(3) # => nil
Class.m(3) < Module.m(3) # => nil
Module.m(3) < Object.m(3) # => nil
Object.m(3) < Class.m(2) # => nil
Class.m(2) < Module.m(2) # => nil
Module.m(2) < Object.m(2) # => nil
Object.m(2) < Class.m # => true
Class.m < Module.m # => true
Module.m < Object.m # => true
Object.m < Class # => true
Class < Module # => true
Module < Object # => true
Object < Kernel # => true

Then, we have to choose between two things: limit the "height" of singleton
class, or correct that inheritence model. I'd be for the first one.
 
A

Ara.T.Howard

Actually the behavior is not consistent - assuming the definition
----
public # create meta objects
def m(height =1)
height.zero? ? self : class << self; self end.m(height -1)
end
----

and the natural inheritance assumption, that the class relation

X < Y # true, implies
X.m < Y.m # true

here we depart. i don't assume this because X's singleton class is just that
: a singleton (eg. one) class with no relation to that of Y's. i think of as
in

class Clothes
end

class Shirts < Clothes
end

class Pants < Clothes
end

class TShirts < Shirts
end

now, obviously, we have something of a hierarchy described in 'is-a' terms:
TShirt 'is-a' Shirt, etc.

now we thow in a __separate__ hierarchy : Pockets. so

class Pocket
end

Pockets, obviously, being where classes store their personal (singleton)
stuff. ;-)

now we have

class Clothes
class Pocket < ::pocket
end
end

class Shirts
class Pocket < ::pocket
end
end

now this is a 'has-a' relationship: a Pants 'has-a' Pocket class
(Pants::pocket) and Shirt 'has-a' Pocket class (Shirt::pocket). there __is__
a subtle 'is-a' relationshiop between pocket classes : a Shirt::pocket 'is-a'
::pocket and a Pant::pocket 'is-a' Pocket. however we do not (necessarily)
have : Shirt::pocket 'is-a' Pants::pocket.

in this case the Pocket class(es) are singleton classes. all classes have one
that descends from a parent singleton class(es). this is a hierarchy that is
related to, but separate and parallel from, the hierachy of any classes which
may themselves have some arbitrary inheritence relationship.

so, for me, it is consistent.

consider the more generic case and it makes much more sense

a = []

class << a
def foo; 42; end
end

a2 = []

class << a2
def bar; 'forty-two'; end
end

surely the search path for

a.bar

should not look into a2's singleton class for it and, conversely,

a2.foo

should not look into a's singleton class. both methods should raise a
NoMethodError. why? because there exists no relationship between the
singleton classes of two instances of a class. in this case the instances are
of class Array, but remember that ruby classes are just instances of class
Class so the same holds true.

so the only reason that

class C; end
class B < C; end

class << C
def foo; 42; end
end
class << B
def bar; 'forty-two'; end
end

permits

B.foo

is __not__ because B.singleton_class < C.singleton_class. rather it is
because the search path for a method is, naturally, up the ancestor list
hierarchy and, at each step along the way, each class additionally looks
'sideways' into it's singleton_class (it's pocket) but not into the
singleton_class of any other classes since, by definition, those classes
belong only to the object that created them - it would be like looking into
someone else's pockets ;-)

cheers.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
E

ES

Le 16/5/2005 said:
here we depart. i don't assume this because X's singleton class is just tha= t
: a singleton (eg. one) class with no relation to that of Y's. i think of a= s
in

class Clothes
end

class Shirts < Clothes
end

class Pants < Clothes
end

class TShirts < Shirts
end

now, obviously, we have something of a hierarchy described in 'is-a' terms:
TShirt 'is-a' Shirt, etc.

now we thow in a __separate__ hierarchy : Pockets. so

class Pocket
end

Pockets, obviously, being where classes store their personal (singleton)
stuff. ;-)

now we have

class Clothes
class Pocket < ::pocket
end
end

class Shirts
class Pocket < ::pocket
end
end

now this is a 'has-a' relationship: a Pants 'has-a' Pocket class
(Pants::pocket) and Shirt 'has-a' Pocket class (Shirt::pocket). there __is_= _
a subtle 'is-a' relationshiop between pocket classes : a Shirt::pocket 'is-a= '
::pocket and a Pant::pocket 'is-a' Pocket. however we do not (necessarily)
have : Shirt::pocket 'is-a' Pants::pocket.

No, that would imply Shirt::pocket < Pants::pocket. However, I
think it is profoundly faulty to imply there is not a significant
relationship between the two. Both children should share the traits
of their parent but not those of their siblings.
in this case the Pocket class(es) are singleton classes. all classes have o= ne
that descends from a parent singleton class(es). this is a hierarchy that i= s
related to, but separate and parallel from, the hierachy of any classes whic= h
may themselves have some arbitrary inheritence relationship.

so, for me, it is consistent.

consider the more generic case and it makes much more sense

a =3D []

class << a
def foo; 42; end
end

a2 =3D []

class << a2
def bar; 'forty-two'; end
end

surely the search path for

a.bar

should not look into a2's singleton class for it and, conversely,

a2.foo

should not look into a's singleton class. both methods should raise a
NoMethodError. why? because there exists no relationship between the
singleton classes of two instances of a class. in this case the instances a= re
of class Array, but remember that ruby classes are just instances of class
Class so the same holds true.

Your analysis is correct but the analogy is not quite, er
analogous. To make it similar, each singleton (or pouch)
would be a subclass of Pocket here. Therefore, while the
methods defined in each of them have no relevance to the
other (siblings' traits are not inherited), they _should_
share the methods from any common ancestors.

So, if child_one.pouch and child_two.pouch are subclasses
of parent.pouch, they should both share any methods in
parent.pouch but not (necessarily) eachother.
so the only reason that

class C; end
class B < C; end

class << C
def foo; 42; end
end
class << B
def bar; 'forty-two'; end
end

permits

B.foo

is __not__ because B.singleton_class < C.singleton_class. rather it is
because the search path for a method is, naturally, up the ancestor list
hierarchy and, at each step along the way, each class additionally looks
'sideways' into it's singleton_class (it's pocket) but not into the
singleton_class of any other classes since, by definition, those classes
belong only to the object that created them - it would be like looking into
someone else's pockets ;-)

This is certainly true.
cheers.

-a

E
 
A

Ara.T.Howard

No, that would imply Shirt::pocket < Pants::pocket.

how do you figure:

harp:~ > cat a.rb
class Pocket; end
class Clothes; class Pocket < ::pocket; end; end
class Shirts; class Pocket < ::pocket; end; end

p Clothes::pocket.ancestors
p Shirts::pocket.ancestors

harp:~ > ruby a.rb
[Clothes::pocket, Pocket, Object, Kernel]
[Shirts::pocket, Pocket, Object, Kernel]

??
However, I think it is > profoundly faulty to imply there is not a
significant relationship between the two.
Both children should share the traits of their parent but not those
of their siblings.

but this is exactly the case? in the above both pocket classes share the
traits of their common parent, Pocket, and neither one shares that of their
siblings. this is precisely the case of singleton classes - they all descend
from [Class, Module, Object, Kernel] (the parent classes) and share those
traits - such as the ability to do 'self.attr :foobar'. i think the mistake
people are making is thinking that by doing

foo = Foo::new

singleton_class = class << foo; self; end

is in thinking that singleton_class 'isa' foo. that is simply not the case.
rather 'singleton_class' is owned by foo. in otherwords foo 'has-a'
singleton_class and their is no parent child relationship between the two.

i think if the syntax were more like

class Foo
singleton_class = generate_a_singleton_class
singleton_class.attr :bar
end

vs.

class Foo
class << self
attr :bar
end
end

this might be more clear. visually the '<<' syntax is similar to '<' in 'A <
B' but it doesn't do anything similar - it only generates a special object
owned by the object calling the '<<' operator.
Your analysis is correct but the analogy is not quite, er
analogous. To make it similar, each singleton (or pouch)
would be a subclass of Pocket here. Therefore, while the
methods defined in each of them have no relevance to the
other (siblings' traits are not inherited), they _should_
share the methods from any common ancestors.

they do. both singletons share the common attributes of their parents:

[Class, Module, Object, Kernel]

again the issue is that

class C
class << self
this_is_a_child_of_Class_not_a_child_of_C = self
end
end

so you are right and the analogy is too - all singleton classes share all the
traits of their common ancestors. it's just that those ancestors don't seem
to be who people think they are ;-)
So, if child_one.pouch and child_two.pouch are subclasses of parent.pouch,
they should both share any methods in parent.pouch but not (necessarily)
eachother.

you'd be right if that were the relationship between parent/child classes and
their respective singleton classes - but with singleton_classes child_one.pouch
is a subclass of Pouch and child_two.pouch is a subclass of Pouch and child_one
and child_two are both children of Parent. check this out closely and you'll
see it for yourself:

harp:~ > cat a.rb
class Class
def pouch; class << self; self; end; end
end
class Parent
p ancestors
p pouch.ancestors
end
class ChildOne < Parent
p ancestors
p pouch.ancestors
end
class ChildTwo < Parent
p ancestors
p pouch.ancestors
end

harp:~ > ruby a.rb

[Parent, Object, Kernel]
[Class, Module, Object, Kernel]

[ChildOne, Parent, Object, Kernel]
[Class, Module, Object, Kernel]

[ChildTwo, Parent, Object, Kernel]
[Class, Module, Object, Kernel]

so the only common ancestors between all the pouches of the above clases are
[Class, Module, Object, Kernel] and they definitely do inherit all the methods
from those ancestors.

note that there is relationship __added__ to the pouches by being pouches of
parent/child classes : all pouches descend from the same Pouch class as in my
Pocket example above.

for some reason i get the feeling we might be saying the same thing an i'm just
saying it badly?

cheers.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
E

ES

Le 16/5/2005 said:
is_=3D
_ s-a=3D
'


No, that would imply Shirt::pocket < Pants::pocket.

how do you figure:

harp:~ > cat a.rb
class Pocket; end
class Clothes; class Pocket < ::pocket; end; end
class Shirts; class Pocket < ::pocket; end; end

p Clothes::pocket.ancestors
p Shirts::pocket.ancestors

harp:~ > ruby a.rb
[Clothes::pocket, Pocket, Object, Kernel]
[Shirts::pocket, Pocket, Object, Kernel]

??

Er, I think I was too curt. I meant to say, "No, we do not necessarily
have Shirt::pocket is-a Pants::pocket, _that_ would imply Shirt::pocket
< Pants::pocket. However..." I was agreeing with you on that point but
disagreeing later :)
but this is exactly the case? in the above both pocket classes share the
traits of their common parent, Pocket, --

Yes, I was merely pointing out that I thought you were perhaps not
describing the relationship of the siblings accurately.
-- and neither one shares that of their
siblings. this is precisely the case of singleton classes - they all descen= d
from [Class, Module, Object, Kernel] (the parent classes) and share those
traits - such as the ability to do 'self.attr :foobar'. i think the mistake
people are making is thinking that by doing

foo =3D Foo::new

singleton_class =3D class << foo; self; end

is in thinking that singleton_class 'isa' foo. that is simply not the case.
rather 'singleton_class' is owned by foo. in otherwords foo 'has-a'
singleton_class and their is no parent child relationship between the two.

Hm, that is a good point, and may well be a common confusion.
i think if the syntax were more like

class Foo
singleton_class =3D generate_a_singleton_class
singleton_class.attr :bar
end

vs.

class Foo
class << self
attr :bar
end
end

this might be more clear. visually the '<<' syntax is similar to '<' in 'A = <
B' but it doesn't do anything similar - it only generates a special object
owned by the object calling the '<<' operator.
Your analysis is correct but the analogy is not quite, er
analogous. To make it similar, each singleton (or pouch)
would be a subclass of Pocket here. Therefore, while the
methods defined in each of them have no relevance to the
other (siblings' traits are not inherited), they _should_
share the methods from any common ancestors.

they do. both singletons share the common attributes of their parents:

[Class, Module, Object, Kernel]

again the issue is that

class C
class << self
this_is_a_child_of_Class_not_a_child_of_C =3D self
end
end

so you are right and the analogy is too - all singleton classes share all th= e
traits of their common ancestors. it's just that those ancestors don't seem
to be who people think they are ;-)
So, if child_one.pouch and child_two.pouch are subclasses of parent.pouch,
they should both share any methods in parent.pouch but not (necessarily)
eachother.

you'd be right if that were the relationship between parent/child classes an= d
their respective singleton classes - but with singleton_classes child_one.po= uch
is a subclass of Pouch and child_two.pouch is a subclass of Pouch and child_= one
and child_two are both children of Parent. check this out closely and you'l= l
see it for yourself:

Agreed! Words fail me again; the 'are' should have been 'were' to
signal a hypothetical.
harp:~ > cat a.rb
class Class
def pouch; class << self; self; end; end
end
class Parent
p ancestors
p pouch.ancestors
end
class ChildOne < Parent
p ancestors
p pouch.ancestors
end
class ChildTwo < Parent
p ancestors
p pouch.ancestors
end

harp:~ > ruby a.rb

[Parent, Object, Kernel]
[Class, Module, Object, Kernel]

[ChildOne, Parent, Object, Kernel]
[Class, Module, Object, Kernel]

[ChildTwo, Parent, Object, Kernel]
[Class, Module, Object, Kernel]

so the only common ancestors between all the pouches of the above clases are
[Class, Module, Object, Kernel] and they definitely do inherit all the metho= ds
from those ancestors.

note that there is relationship __added__ to the pouches by being pouches of
parent/child classes : all pouches descend from the same Pouch class as in m= y
Pocket example above.

for some reason i get the feeling we might be saying the same thing an i'm j= ust
saying it badly?

I are both think we uncommunicating miswell.

Yes, I generally agree with what you are saying, definitely. My
objection was merely to you (to me) not describing the 'common
lineage' of the two singletons/pouches correctly, rather than
the entire explanation. I was not clear about this, sorry.
cheers.

-a

E
 
A

Ara.T.Howard

Er, I think I was too curt. I meant to say, "No, we do not necessarily have
Shirt::pocket is-a Pants::pocket, _that_ would imply Shirt::pocket <
Pants::pocket. However..." I was agreeing with you on that point but
disagreeing later :)

ah - i'm on board now.
Hm, that is a good point, and may well be a common confusion.

it confused me! ;-)
Agreed! Words fail me again; the 'are' should have been 'were' to signal a
hypothetical.

o.k. - we're on a roll!
I are both think we uncommunicating miswell.

who? what? where?
Yes, I generally agree with what you are saying, definitely. My objection
was merely to you (to me) not describing the 'common lineage' of the two
singletons/pouches correctly, rather than the entire explanation. I was not
clear about this, sorry.

no problem. i had to really struggle to figure all this out for my traits.rb
lib and am still looking for any opportunity to refine my understanding -
which was the entire motivation for the long post : i'm trying to make
__sure__ i know what i think i know.

ciao.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
L

Lionel Thiry

(e-mail address removed) a écrit :
Actually the behavior is not consistent - assuming the definition
----
public # create meta objects
def m(height =1)
height.zero? ? self : class << self; self end.m(height -1)
end
----

and the natural inheritance assumption, that the class relation

X < Y # true, implies
X.m < Y.m # true


here we depart. i don't assume this because X's singleton class is just
that
: a singleton (eg. one) class with no relation to that of Y's.

[snip]

so the only reason that

class C; end
class B < C; end

class << C
def foo; 42; end
end
class << B
def bar; 'forty-two'; end
end

permits

B.foo

is __not__ because B.singleton_class < C.singleton_class. rather it is
because the search path for a method is, naturally, up the ancestor list
hierarchy and, at each step along the way, each class additionally looks
'sideways' into it's singleton_class (it's pocket) but not into the
singleton_class of any other classes since, by definition, those classes
belong only to the object that created them - it would be like looking into
someone else's pockets ;-)

http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/140562

If you really want ruby2 works the way you described it, I advice you to
urgently post an RCR for it.
 
A

Ara.T.Howard


yes i saw that.
If you really want ruby2 works the way you described it, I advice you to
urgently post an RCR for it.

no. the new behaviour is fine - i was simply describing how it is now and how
that relates to the 'infinite levels' issue in that i think it's strange -
but consistent. believe me - you've no idea how much easier my trait lib
would have been to write if

child.singleton_class < parent.singleton_class

as it were i had to do this

class << self
# determine our 'singleton_super' so we can use it's ancestors
end

and this is precisely because parent/child meta classes do not fit into the
same kind of hierarchy as their respective classes. so i will love the new
behaviour.

i'm going to quit on this now because i feel like i've only confused things.
sorry if i have.

cheers.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| renunciation is not getting rid of the things of this world, but accepting
| that they pass away. --aitken roshi
===============================================================================
 
C

Christoph

no. the new behaviour is fine - i was simply describing how it is now
and how
that relates to the 'infinite levels' issue in that i think it's
strange -
but consistent. believe me - you've no idea how much easier my trait lib
would have been to write if

child.singleton_class < parent.singleton_class


Well it would be nice if this were true, but it's not - "higher order"
singleton class
behavior changed quite a bit in the past and it so again from 1.82 to
todays cvs.
Lionel point was because Ruby does not seem to have a consistent treatment
(consitency is always relative to the reades eyes) of these "higher
order" singleton
classes, they should be forbidden in the first place. I ran the
following script
with a standard 1.82, todays cvs.

----
puts RUBY_VERSION
public # create meta objects

def m(height =1)
height.zero? ? self : class << self; self end.m(height -1)
end

base = [Object,Module, Class]
require 'enumerator'

(0..11).each_cons(2) do |a,b|
d0,r0 = a.divmod(3)
d1,r1 = b.divmod(3)
rel = base[r0].m(d0) > base[r1].m(d1)
puts "#{base[r0]}.m(#{d0}) > #{base[r1]}.m(#{d1}) # #{rel}"
end

class A; end
class B < A; end

def q(s)
puts s << " # #{eval(s)}"
end

puts "\n###","\n"
q "B.new.m(5) < B.m(4)"
q "B.m(4) < A.m(4)"
q "A.m(4) < Object.m(4)"

puts "\n### print superclass chain","\n"
class Class
alias succ superclass
end

(1..8).each do |i|
puts ((B.new.m(i)..Object).to_a.join(" : "))
end
---

These were the two outputs

---
1.9.0
Object.m(0) > Module.m(0) # true
Module.m(0) > Class.m(0) # true
Class.m(0) > Object.m(1) # true
Object.m(1) > Module.m(1) # true
Module.m(1) > Class.m(1) # true
Class.m(1) > Object.m(2) # false
Object.m(2) > Module.m(2) # false
Module.m(2) > Class.m(2) # false
Class.m(2) > Object.m(3) # true
Object.m(3) > Module.m(3) # false
Module.m(3) > Class.m(3) # false

###

B.new.m(5) < B.m(4) # true
B.m(4) < A.m(4) # false
A.m(4) < Object.m(4) # false
### print superclass chain

#<Class:#<B:0x101030a0>> : B : A : Object
Class : Module : Object
#<Class:Class> : #<Class:Module> : #<Class:Object> : Class : Module : Object
Class : Module : Object
#<Class:Class> : #<Class:Module> : #<Class:Object> : Class : Module : Object
Class : Module : Object
#<Class:Class> : #<Class:Module> : #<Class:Object> : Class : Module : Object
Class : Module : Object
---
and
---
1.8.2
Object.m(0) > Module.m(0) # true
Module.m(0) > Class.m(0) # true
Class.m(0) > Object.m(1) # true
Object.m(1) > Module.m(1) #
Module.m(1) > Class.m(1) # true
Class.m(1) > Object.m(2) # true
Object.m(2) > Module.m(2) #
Module.m(2) > Class.m(2) #
Class.m(2) > Object.m(3) #
Object.m(3) > Module.m(3) #
Module.m(3) > Class.m(3) #

###

B.new.m(5) < B.m(4) #
B.m(4) < A.m(4) #
A.m(4) < Object.m(4) #
### print superclass chain

#<Class:#<B:0x2793bc8>> : B : A : Object
#<Class:#<Class:#<B:0x2793a60>>> : #<Class:B> : #<Class:A> :
#<Class:Object> : Class : Module : Object
#<Class:#<Class:#<Class:#<B:0x2793820>>>> : #<Class:Class> :
#<Class:Module> : #<Class:Object> : Class : Module : Object
#<Class:#<Class:#<Class:#<Class:#<B:0x2793598>>>>> : #<Class:Class> :
#<Class:Module> : #<Class:Object> : Class : Module : Object
#<Class:#<Class:#<Class:#<Class:#<Class:#<B:0x27932c8>>>>>> :
#<Class:Class> : #<Class:Module> : #<Class:Object> : Class : Module : Object
#<Class:#<Class:#<Class:#<Class:#<Class:#<Class:#<B:0x2792fb0>>>>>>> :
#<Class:Class> : #<Class:Module> : #<Class:Object> : Class : Module : Object
#<Class:#<Class:#<Class:#<Class:#<Class:#<Class:#<Class:#<B:0x2792c50>>>>>>>>
: #<Class:Class> : #<Class:Module> : #<Class:Object> : Class : Module :
Object
#<Class:#<Class:#<Class:#<Class:#<Class:#<Class:#<Class:#<Class:#<B:0x27928a8>>>>>>>>>
: #<Class:Class> : #<Class:Module> : #<Class:Object> : Class : Module :
Object
---


as it were i had to do this

class << self
# determine our 'singleton_super' so we can use it's ancestors
end

and this is precisely because parent/child meta classes do not fit
into the
same kind of hierarchy as their respective classes. so i will love
the new
behaviour.

i'm going to quit on this now because i feel like i've only confused
things.
sorry if i have.


I promise I will quit this too, well after this post:)

/Christoph
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,275
Latest member
Michaelachoda

Latest Threads

Top