infinite number of singleton_classes

L

Lionel Thiry

Hello!

----8<----
a = Object.new

b = class << a
class << self
class << self
class << self
# "class << self".times(n)
self
# "end".times(n)
end
end
end
end
# => #<Class:#<Class:#<Class:#<Class:#<Object:0x2aa8348>>>>>
----8<----

How many levels can we reach? It seems there is no limit.

I suppose those singleton_class exists only when needed? Otherwise, I really
wonder where does ruby hide all those singleton_classes...

But, sincerely, is it needed to have the singleton_class of a singleton_class?
Isn't it a non-sense? Shouldn't this raise an error?

---8<---
a = Object.new

begin
b = class << a
class << self
self
end
end
rescue NewError
puts "Sincerely, you don't need the singleton_class of the singleton_class!"
end
---8<---

What do you think of it? Isn't it worth an RCR?
 
C

Christoph

Lionel said:
How many levels can we reach? It seems there is no limit.

I suppose those singleton_class exists only when needed? Otherwise, I really
wonder where does ruby hide all those singleton_classes...

But, sincerely, is it needed to have the singleton_class of a singleton_class?
Isn't it a non-sense? Shouldn't this raise an error?
I agree, it should not be possible to these classes ...
---8<---
a = Object.new

begin
b = class << a
class << self
self
end
end
rescue NewError
puts "Sincerely, you don't need the singleton_class of the singleton_class!"
end
---8<---

What do you think of it? Isn't it worth an RCR?
Yes lets get rid of them, they are utterly useless and
a source of distraction (well at least they have been
in past for me:)

/Christoph
 
A

Ara.T.Howard

Hello!

----8<----
a = Object.new

b = class << a
class << self
class << self
class << self
# "class << self".times(n)
self
# "end".times(n)
end
end
end
end
# => #<Class:#<Class:#<Class:#<Class:#<Object:0x2aa8348>>>>>
----8<----

How many levels can we reach? It seems there is no limit.

I suppose those singleton_class exists only when needed? Otherwise, I really
wonder where does ruby hide all those singleton_classes...

But, sincerely, is it needed to have the singleton_class of a singleton_class?
Isn't it a non-sense? Shouldn't this raise an error?

---8<---
a = Object.new

begin
b = class << a
class << self
self
end
end
rescue NewError
puts "Sincerely, you don't need the singleton_class of the singleton_class!"
end
---8<---

What do you think of it? Isn't it worth an RCR?


i've found them useful in the following situation:

harp:~ > cat a.rb
class C
class << self
class << self
def class_method_generator name
module_eval <<-code
def #{ name }; @#{ name }; end
alias #{ name }? #{ name }
def #{ name }= value; @#{ name } = value; end
code
end
end
%w( a b c ).each{|meth| class_method_generator meth}
end
end

class B < C
end

C.a = 42
p C.a

B.a = 'forty-two'
p B.a

C.class_method_generator :x


harp:~ > ruby a.rb
42
"forty-two"
a.rb:25: undefined method `class_method_generator' for C:Class (NoMethodError)

granted, you could do this with a private class method of C - but this is what
singleton methods are for : defining a method on 'this' instance right here
and right now that only that instance should be able to do. in this case the
instance happens to be a singleton of a singleton.

in any case i don't think one can say when/if that construct would be useful a
priori and think that having that notion enforced by ruby itself ( __i__ know
when need a singleton class and __you__ don't ) is the kind of exception that
reminds of of a 'p' language. ruby programmers are continually pushing the
boundries of oo coding precisely because matz has given them the tools to do
so and 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__.

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
===============================================================================
 
D

David A. Black

Hi --

Hello!

----8<----
a = Object.new

b = class << a
class << self
class << self
class << self
# "class << self".times(n)
self
# "end".times(n)
end
end
end
end
# => #<Class:#<Class:#<Class:#<Class:#<Object:0x2aa8348>>>>>
----8<----

How many levels can we reach? It seems there is no limit.

I suppose those singleton_class exists only when needed? Otherwise, I really
wonder where does ruby hide all those singleton_classes...

But, sincerely, is it needed to have the singleton_class of a singleton_class?
Isn't it a non-sense? Shouldn't this raise an error?
[...]

What do you think of it? Isn't it worth an RCR?

No; it's just a consequence of the underlying design principles. Yes,
there are a few objects that can't have a singleton class (Fixnums and
Symbols are the ones I can think of). But Class objects can, and
singleton classes are Class objects. So you'd be asking for
special-case treatment for a subset of classes.

It would be a bit like saying: Surely no one will ever use a
singleton class as a hash key, so let's remove the #hash method from
it. There's just no reason to constrain the language and its usage
that way.

Also, I don't see any harm or danger here. I suppose one could
accidentally write a loop that kept creating singleton classes, but
one could also write a loop that kept creating *non*-singleton classes
-- or arrays, or hashes, or MyClass objects, and so on.


David
 
L

Lionel Thiry

(e-mail address removed) a écrit :
i've found them useful in the following situation:

harp:~ > cat a.rb
class C
class << self
class << self
def class_method_generator name
module_eval <<-code
def #{ name }; @#{ name }; end
alias #{ name }? #{ name }
def #{ name }= value; @#{ name } = value; end
code
end
end
%w( a b c ).each{|meth| class_method_generator meth}
end
end

class B < C
end

C.a = 42
p C.a

B.a = 'forty-two'
p B.a

C.class_method_generator :x


harp:~ > ruby a.rb
42
"forty-two"
a.rb:25: undefined method `class_method_generator' for C:Class
(NoMethodError)

granted, you could do this with a private class method of C - but this
is what
singleton methods are for : defining a method on 'this' instance right here
and right now that only that instance should be able to do. in this
case the
instance happens to be a singleton of a singleton.

in any case i don't think one can say when/if that construct would be
useful a
priori and think that having that notion enforced by ruby itself ( __i__
know
when need a singleton class and __you__ don't ) is the kind of exception
that
reminds of of a 'p' language. ruby programmers are continually pushing the
boundries of oo coding precisely because matz has given them the tools
to do
so and 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__.

kind regards.

-a

I just ask for opinions, you know... :(

What did make you so angry? The fact that I've thought it could be worth an RCR?
 
H

Hal Fulton

Lionel said:
I just ask for opinions, you know... :(

What did make you so angry? The fact that I've thought it could be worth an RCR?

You have misunderstood somewhere. Ara was not angry.

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


Hal
 
C

Christoph

David said:
Also, I don't see any harm or danger here. I suppose one could
accidentally write a loop that kept creating singleton classes, but
one could also write a loop that kept creating *non*-singleton classes
-- or arrays, or hashes, or MyClass objects, and so on.

At least you can print any self referential (looping) object involving the
standard container classes, Hash, Arrays. Structs and Sets- however

---
class O
end

CrashChild = class << O; self end.dup

Crash = class << CrashChild
superclass
end

Crash.inspect
---

results in a system stack overflow (for the "stock 1.8.2 windows
installer" ruby). This probably has to do with the fact that the
superclass of a normal "singleton singleton class" of a class, is
necessarily equal to

Klass = class << Class; self end # singleton class of class Class, e.g.
---
class O
end

nocrash = class << (class << O; self end)
superclass
end

Klass = class << Class; self end

p (nocrash == Klass) # true
---

The core problem is (I assume because of efficiency reasons), that Matz
took "a little short cut" of not creating the natural chain of "higher
order"
singleton classes, and cheated by declaring the superclass of any
"higher order" singleton class to be Klass.

Instead of going to the trouble of implementing an ad hoc "higher order
singleton class scheme" (b.t.w. - Ruby had a completely different higher
order singleton class scheme in past) it might have been wiser,
well at least less work, of preventing the creation of "higher order"
singleton classes in the first place.

/Christoph
 
D

David A. Black

Hi --

The core problem is (I assume because of efficiency reasons), that Matz
took "a little short cut" of not creating the natural chain of "higher order"
singleton classes, and cheated by declaring the superclass of any
"higher order" singleton class to be Klass.

Instead of going to the trouble of implementing an ad hoc "higher order
singleton class scheme" (b.t.w. - Ruby had a completely different higher
order singleton class scheme in past) it might have been wiser,
well at least less work, of preventing the creation of "higher order"
singleton classes in the first place.

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

I don't think having (class << Class; self; end) be the superclass of
these singletons is a problem. At least, if one had a reason to want
to go higher than one level (for example, adding a class method to a
singleton class -- has anyone done that?), it wouldn't really matter
what the class's superclass was.


David
 
L

Lionel Thiry

Hal Fulton a écrit :
You have misunderstood somewhere. Ara was not angry.

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

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?
 
L

Lionel Thiry

David A. Black a écrit :
Hi --

Hello!

----8<----
a = Object.new

b = class << a
class << self
class << self
class << self
# "class << self".times(n)
self
# "end".times(n)
end
end
end
end
# => #<Class:#<Class:#<Class:#<Class:#<Object:0x2aa8348>>>>>
----8<----

How many levels can we reach? It seems there is no limit.

I suppose those singleton_class exists only when needed? Otherwise, I
really
wonder where does ruby hide all those singleton_classes...

But, sincerely, is it needed to have the singleton_class of a
singleton_class?
Isn't it a non-sense? Shouldn't this raise an error?

[...]

What do you think of it? Isn't it worth an RCR?


No; it's just a consequence of the underlying design principles. Yes,
there are a few objects that can't have a singleton class (Fixnums and
Symbols are the ones I can think of). But Class objects can, and
singleton classes are Class objects. So you'd be asking for
special-case treatment for a subset of classes.

It would be a bit like saying: Surely no one will ever use a
singleton class as a hash key, so let's remove the #hash method from
it. There's just no reason to constrain the language and its usage
that way.

Also, I don't see any harm or danger here. I suppose one could
accidentally write a loop that kept creating singleton classes, but
one could also write a loop that kept creating *non*-singleton classes
-- or arrays, or hashes, or MyClass objects, and so on.

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.

Then, giving that fact as true, for the sake of future ruby versions, wouldn't
it be more consistent to forbid singleton class of singleton class?

I may admit that the such said "sake of future ruby versions" may need some
other marginal never truly used features be forbidden either. I don't know, I'm
not sure of anything.

And, please note this: I agree with you. There is nothing wrong or harmfull in
the current behavior, while looking from the point of view of a ruby user. But I
think it may be different from the point of view of a language designer and I
like to take count of it.
 
D

David A. Black

Hi --

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.

Then, giving that fact as true, for the sake of future ruby versions, wouldn't
it be more consistent to forbid singleton class of singleton class?

It would only be consistent to forbid them if singleton classes
themselves cease to exist (in some future Ruby implementation). As
long as objects have singleton classes, and as long as those classes
are objects, it's consistent for them, too, to have singleton classes.

The closest thing to a possible use I can think of is class methods
(including accessors) on a singleton class -- like this:

obj = Object.new
c = class << obj; self; end
c.class_eval { class << self; attr_accessor :x; end }
c.x = 123

etc. But it's probably a bit of a stretch. Still, I don't feel that
there's any reason for c (in that example) not to be allowed to create
class methods (i.e., singleton methods for itself).


David
 
C

Christoph

David said:
I'd rather just see the #inspect bug fixed :)

I don't think having (class << Class; self; end) be the superclass of
these singletons is a problem. At least, if one had a reason to want
to go higher than one level (for example, adding a class method to a
singleton class -- has anyone done that?), it wouldn't really matter
what the class's superclass was.

If you are "singleton class" you only have to do house keeping for a one
instance only. There is a potential benefit of inheriting house keeping
methods
but this is broken if Klass is the superclass of all "higher order"
singleton
classes. If inheritance does not work any more "higher order" singleton
classes
are pretty much fake "higher order" singleton classes.

---
# From Ara example
class C
class << self
class << self
def class_method_generator name
module_eval <<-code
def #{ name }; @#{ name }; end
alias #{ name }? #{ name }
def #{ name }= value; @#{ name } = value; end
code
end
end
%w( a b c ).each{|meth| class_method_generator meth}
end
end

class B < C
end

C.a = 42
p C.a

B.a = 'forty-two'
p B.a

class << B
class << self
class_method_generator :wont_work_in_182
end
end
 
D

David A. Black

Hi --

If you are "singleton class" you only have to do house keeping for a one
instance only. There is a potential benefit of inheriting house keeping
methods
but this is broken if Klass is the superclass of all "higher order" singleton
classes. If inheritance does not work any more "higher order" singleton
classes
are pretty much fake "higher order" singleton classes.

Here's another interesting variant:

Klass = class << Class; self; end
def Klass.m; puts "here"; end

class C; end
class << C
class << self
p superclass == Klass # true
Klass.m # "here"
m # NoMethodError
end
end

i.e, having Klass as your superclass does not give you access to
Klass's class methods. I'm not sure whether I think this makes it
more consistent (explained in a moment) or whether it makes the whole
thing, as you say, kind of fake.

By "more consistent", I mean:

Having a subclass able to call its superclass's singleton (class)
methods is, as far as I know, the only case where one object can call
another's singleton methods. This arrangement seems to disappear in
the case of singleton classes of singleton classes... but at least it
disappears consistently (i.e., even in the case of "Klass" above).

Or something. In practical terms there's probably not much mileage to
be had out of these.


David
 
C

Christoph

David said:
:

Having a subclass able to call its superclass's singleton (class)
methods is, as far as I know, the only case where one object can call
another's singleton methods. This arrangement seems to disappear in
the case of singleton classes of singleton classes... but at least it
disappears consistently (i.e., even in the case of "Klass" above).

It also works if the subclass is an ordinary singleton class of an
instance of the superclass.
Or something. In practical terms there's probably not much mileage to
be had out of these.

True - but when there is very little mileage why not simply disallow them in
the first place.

As a side note the class Klass lends itself naturally as the mother of all
singleton classes - i.e. "pouch == Klass" - a problem with this idea is that
we currently have Class < Module < Object.

/Christoph
 
D

David A. Black

Hi --

It also works if the subclass is an ordinary singleton class of an
instance of the superclass.


True - but when there is very little mileage why not simply disallow them in
the first place.

I'm just not ready for:

class << obj; def self.x; end; end

to throw an error. It just seems like taking away too much
class-ness -- though obviously if the class interface to object
singleton behavior disappears entirely, that won't be an issue.
As a side note the class Klass lends itself naturally as the mother of all
singleton classes - i.e. "pouch == Klass" - a problem with this idea is that
we currently have Class < Module < Object.

I'm not sure what you mean. If every object's "pouch" is Klass, it
will get very crowded.... But I think I'm misunderstanding.


David
 
L

Lionel Thiry

David A. Black a écrit :
Hi --




It would only be consistent to forbid them if singleton classes
themselves cease to exist (in some future Ruby implementation). As
long as objects have singleton classes, and as long as those classes
are objects, it's consistent for them, too, to have singleton classes.

You have skipped this part of my post in your answer:
----8<----
And, please note this: I agree with you. There is nothing wrong or harmfull in
the current behavior, while looking from the point of view of a ruby user. But I
think it may be different from the point of view of a language designer and I
like to take count of it.
----8<----

The feature is currently avaible, but unless Matz state otherwise, it is an
accident, it shouldn't have never happened. Why? Because it may disapear in any
future version of ruby. Who said it? Matz himself. It then should be accessible
only via special module like evil.rb if one really want the feature.

On the other hand, if it was said that ruby won't never change about singleton
methods hold in singleton classes, I wouldn't care at all about this.
 
C

Christoph

David said:
I'm just not ready for:

class << obj; def self.x; end; end

to throw an error. It just seems like taking away too much
class-ness -- though obviously if the class interface to object
singleton behavior disappears entirely, that won't be an issue.

I was kind of proposing to throw an error at the next level

class << obj; class << self def self.x; end; end; end

Disallowing the formation of the "singleton singleton class" of
any type of class including "singleton classes" - this would
effectively kill Ara's usage example
I'm not sure what you mean. If every object's "pouch" is Klass, it
will get very crowded.... But I think I'm misunderstanding.

Singleton classes could be instances of Klass, essentially Klass would
be a subclass
and "singleton class" of Class at the same time. This is similar (kind
of the higher order
version of) of Matju's proposed identification.

class << Object; self end == Class


/Christoph
 
D

David A. Black

You have skipped this part of my post in your answer:
----8<----
And, please note this: I agree with you. There is nothing wrong or harmfull in
the current behavior, while looking from the point of view of a ruby user. But I
think it may be different from the point of view of a language designer and I
like to take count of it.
----8<----

I didn't have anything to add to it, so I didn't quote it back.
Otherwise we get into infinite recursion :)
The feature is currently avaible, but unless Matz state otherwise, it is an
accident, it shouldn't have never happened. Why? Because it may disapear in any
future version of ruby. Who said it? Matz himself. It then should be accessible
only via special module like evil.rb if one really want the feature.

If it disappears, it can't be accessible from any module, at least not
in exactly that form.
On the other hand, if it was said that ruby won't never change about singleton
methods hold in singleton classes, I wouldn't care at all about this.

There's a bit of a paradox there. If Ruby shouldn't contain anything
that might be absent in a future Ruby, then Ruby today must be exactly
what Ruby in the future will be.... If singleton classes disappear,
lots of things will change, possibly including:

class << obj # this form of the class keyword
X = 1 # constants -- where would this go?
def self.x # class methods on the singleton class
end
end

as well as just the fact that you can call Class's instance methods,
in general, on singleton classes.

So if you apply the rule: it should never have happened because it
may disappear in a future version of Ruby, then all of this should
never have happened and should disappear. But so should lots of other
things, because Matz is planning lots of changes. So that means Ruby
should be turned into future Ruby *now*. But that takes time :)


David
 
D

David A. Black

Hi --

I was kind of proposing to throw an error at the next level

class << obj; class << self def self.x; end; end; end

Disallowing the formation of the "singleton singleton class" of
any type of class including "singleton classes" - this would
effectively kill Ara's usage example

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.)
Singleton classes could be instances of Klass, essentially Klass would be a
subclass
and "singleton class" of Class at the same time. This is similar (kind of the
higher order
version of) of Matju's proposed identification.

class << Object; self end == Class

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....


David
 
L

Lionel Thiry

David A. Black a écrit :
I didn't have anything to add to it, so I didn't quote it back.
Otherwise we get into infinite recursion :)



If it disappears, it can't be accessible from any module, at least not
in exactly that form.

I should have added "Until it disapears (if it disapears), it should be
accessible only via...". Sorry.
There's a bit of a paradox there. If Ruby shouldn't contain anything
that might be absent in a future Ruby, then Ruby today must be exactly
what Ruby in the future will be.... If singleton classes disappear,
lots of things will change, possibly including:

class << obj # this form of the class keyword
X = 1 # constants -- where would this go?
def self.x # class methods on the singleton class
end
end

as well as just the fact that you can call Class's instance methods,
in general, on singleton classes.

So if you apply the rule: it should never have happened because it
may disappear in a future version of Ruby, then all of this should
never have happened and should disappear. But so should lots of other
things, because Matz is planning lots of changes. So that means Ruby
should be turned into future Ruby *now*. But that takes time :)


My "why?" argument was insuficiant, I admit it. Sorry.

Future version of ruby will change... but the ruby way/feeling will not. This is
the garantee Matz has given us for ruby2, AFAIK. And IMO I think the presence or
the absence of that feature matters a lot for defining that ruby way.

For example, the fact that
----8<----
class << obj
X = 1
def self.x
end
end
----8<----
could disapear implies a lot on the ruby way.
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,139
Latest member
JamaalCald
Top