Singleton classes and methods (was Re: Reformat Ruby source

On 8/28/06, James Edward G. II [email protected] wrote:

On Aug 28, 2006, at 12:26 PM, Robert D. wrote:

Not at all. That’s why I said “singleton class” in the first place.

Hey man, all this singleton class stuff is just finally starting to
sink into my brain, don’t set me back on the path to enlightenment! :wink:

Singleton classes are a slippery concept, and singleton methods even
more so. IMHO, the terminology comes from a bit of the
implementation. I’ve been slogging through the 1.8 implementation in
order to understand what’s really going on. Just what is the
definition of a singleton class, or a singleton method?

In the 1.8 implementation, a singleton class seems to be a class which
has a flag bit called FL_SINGLETON set in its object header. This
appears to be the ‘virtual’ bit alluded to in Chapter 24 of the
pickaxe 2nd ed. There really isn’t a flag named FL_VIRTUAL or
anything like that, but there are a couple of places where the
FL_SINGLETON bit is checked and an exception is raised with a message
of the form, “you can’t do that with a virtual class”.

If a singleton class is a class which is tied to one and only one
object, then a singleton method should be a method tied to one and
only one object as well, but check this out:

class X
def foo;end
end

X.singleton_methods => [“foo”]

class Y < X; end

Y.singleton_methods => [“foo”]

Does anyone beside me find that surprising? Now the rdoc of
Object#singleton_methods says that it takes an optional boolean
argument which if false will include methods in modules included in
obj.

Y.singleton_methods(false) => []

So does Y include X?

Y.include? X
TypeError: wrong argument type Class (expected Module)
from (irb):29:in `include?’
from (irb):29

By the way, another piece of the 1.8 implementation is the type field
in the object header, this is actually the low-order 4 bits of the
flag field, and it’s used as kind of a union discriminator to indicate
which of several C structs map the remainder of the object’s ‘box.’
One of the type codes is T_ICLASS which is a pseudo-type, which means
that the object looks like a class, but it’s actually a proxy for a
module included in the class.

Actually, unlike singleton classes of instances, which can’t have
subclasses, singleton classes of classes can, and will if the class
which owns one has a subclass itself.

Looking at the code which implements singleton_methods it creates an
empty array, and then looks to see if the class of self is flagged as
a singleton, and if so adds the method names from its method table to
the array. Then, if the argument is true, it walks up the superclass
chain while the class it’s looking at is either marked with
FL_SINGLETON or has a type of T_ICLASS, and adds those methods.

So the operational definition of a singleton methods seems to be a
method of an object which appears in a singleton class or a module
mixed directly INTO a singleton class, or comes from a singleton class
which is in the superclass chain of the objects class BEFORE a non
singleton class, or a module directly mixed into one of those
singleton classes. Whew.

Note that in the paragraph above, ‘singleton class’ means a class
whose FL_SINGLETON flag bit is set. Which I guess IS the definition
of a singleton class.

It might just be me, but I find the use of singleton class both to
provide instance behaviour, and to serve the purpose of a metaclass a
liitle too much the product of the implementation, leading to
confusion.

To my mind, the name singleton class implies that it should provide
methods to a single instance. Singleton classes of classes don’t do
this. Normally singleton classes refuse to be subclassed, but
singleton classes of classes get subclassed ‘under the covers’ when
their class gets subclassed.

The code which implements singleton_methods seems to be trying to
produce a list of methods which are available only to the instance
associated with a singleton class, but this breaks down for singleton
classes of classes since it also lists inherited ‘singleton’ methods,
which since there’s no real distinction that I can see between
singleton methods of a class and class methods, means that it lists
all inherited class methods of a class. Perhaps it’s just a bug and
the singleton_classes implementation should only look at T_ICLASSes
after the initial singleton class.

It appears that a lot of the reason for FL_SINGLETON and T_ICLASS is
to hide a slightly tricky implementation from showing through some of
the reflection methods. Perhaps Ruby would be a little cleaner if it
just called a metaclass a metaclass, and a singleton class a singleton
class, and reserved the later for a class providing behavior for a
single instance. But that’s just my opinion and it’s not the way
things are.

I just realized that there’s no class_methods family of methods in
Ruby. I can’t say:

Array.class_methods

instead I have to say:
Array.singleton_methods

While I can say
Array.private_instance_methods

How do I get the private_class_methods?

Well, such musings are probably a bit like arguing about how many
angels can dance on the head of a pin, but I hope someone else finds
them interesting.

Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Hi –

On Wed, 30 Aug 2006, Rick DeNatale wrote:

class Y < X; end

Y.singleton_methods => [“foo”]

Does anyone beside me find that surprising?

It’s always struck me as an anomaly. It’s redeemed somewhat by the
superclass thing, whereby class << X is the superclass of class << Y.
(At least, in 1.8.2 and > 1.8.5 it is; I’m not sure why that got
derailed by 1.8.4, since it still behaves that way.)

  from (irb):29:in `include?'
  from (irb):29

I’m not sure what you’re getting at here. Are you thinking of whether
Y’s ancestors include X?

So the operational definition of a singleton methods seems to be a
method of an object which appears in a singleton class or a module
mixed directly INTO a singleton class, or comes from a singleton class
which is in the superclass chain of the objects class BEFORE a non
singleton class, or a module directly mixed into one of those
singleton classes. Whew.

It’s not too hard if you draw it :slight_smile: It’s basically just a bunch of
classes and modules, with the object walking through them looking for
a method.

[…]

It appears that a lot of the reason for FL_SINGLETON and T_ICLASS is
to hide a slightly tricky implementation from showing through some of
the reflection methods. Perhaps Ruby would be a little cleaner if it
just called a metaclass a metaclass, and a singleton class a singleton
class, and reserved the later for a class providing behavior for a
single instance. But that’s just my opinion and it’s not the way
things are.

I tend to call the singleton classes of classes singleton classes (did
you follow that? :slight_smile: in part because the term “metaclass” doesn’t do
much for me. But the singleton-ness of them is definitely in
question.

I just realized that there’s no class_methods family of methods in
Ruby. I can’t say:

Array.class_methods

instead I have to say:
Array.singleton_methods

Now that’s the cool part :slight_smile: I love the fact that there’s no
language-level notion of a “class method”. In general, Ruby has this
way of providing a remarkably featureless (I use the word advisedly)
landscape, out of the featurelessness of which one can mold features.
So if you feel like there should be class methods, you can tap into
the fact that class objects can have singleton(ish) methods. But as
far as Ruby is concerned, there’s no special case.

Frequently, the special cases and constructs in Ruby are in the eye of
the beholder, so to speak. I put “attributes” in that category too,
even though the presence of the attr_* methods makes that a somewhat
more language-supported thing.

It’s also why I dislike class variables so much. They’re a
language-level feature that I think can be done better using a blend
of other features.

While I can say
Array.private_instance_methods

How do I get the private_class_methods?

class << Array; private_instance_methods(false); end

or something along those lines.

David

On 8/29/06, [email protected] [email protected] wrote:

end
superclass thing, whereby class << X is the superclass of class << Y.
(At least, in 1.8.2 and > 1.8.5 it is; I’m not sure why that got
derailed by 1.8.4, since it still behaves that way.)

So was there a change in 1.8.3 which got backed out in 1.8.5?
What was it?

  from (irb):29:in `include?'
  from (irb):29

I’m not sure what you’re getting at here. Are you thinking of whether
Y’s ancestors include X?

No, I was getting to the actual vs. stated behavior of
singleton_methods(true). The Rdoc says that if the argument is true
(the default now) then methods from included MODULES will also be
reported, but X is not an included module. It’s a class and classes
can’t be included, instead X’s singleton class is a superclass of Y’s
singleton class.

And by the way, I’m surprised that neither you nor anyone else caught
my typo in the initial definition of X which should have been:

class X;def X.foo;end;end

In order to make foo a singleton/class method.

So the operational definition of a singleton methods seems to be a
method of an object which appears in a singleton class or a module
mixed directly INTO a singleton class, or comes from a singleton class
which is in the superclass chain of the objects class BEFORE a non
singleton class, or a module directly mixed into one of those
singleton classes. Whew.

It’s not too hard if you draw it :slight_smile: It’s basically just a bunch of
classes and modules, with the object walking through them looking for
a method.

I didn’t say it was hard, just that I ran out of breath typing that
sentence.

It also seems to me that some of these anomalies in the results of
some of the reflection methods show too much of the cogs (like
FL_SINGLETON and T_ICLASS) which Matz seems to be trying to hide.

I tend to call the singleton classes of classes singleton classes (did
you follow that? :slight_smile: in part because the term “metaclass” doesn’t do
much for me. But the singleton-ness of them is definitely in
question.

And that’s my observation/question. Just what does the singleton-ness
of a class really means.

There doesn’t seem to be enough to go on here in formal documentation.
We’re left pondering what it means as the result of experiments to a
large extent, and/or trying to suss it out by reading implementation
code to infer the intent.

And the code might just be a little cleaner if the classes which
provide behavior to sub-classes of Class were implemented with a
separate internal type instead of being cooked up using a combination
of FL_SINGLETON and special cases in the code.

As for the term metaclass, personally I think that things would be
more understandable if Ruby used an official term for the object which
holds the behavior of a class object. Metaclass seems like it fits
that concept quite well. The pickaxe quotes Matz as saying that
although those things are singleton classes of classes, that they
behave just like Smalltalk metaclasses.

I can understand the tension between the implementation buying off on
an official metaclass concept and how that might affect implementing
some of Matz’ wild ideas in the future, since it would somehow dictate
parts of future implementations, but on the other hand the way it is
now, with the implementation observable “through a glass darkly,”
protection of the freedom to pursue new implementations seems to be
through a form of “security through obscurity.”

language-level notion of a “class method”. In general, Ruby has this
way of providing a remarkably featureless (I use the word advisedly)
landscape, out of the featurelessness of which one can mold features.
So if you feel like there should be class methods, you can tap into
the fact that class objects can have singleton(ish) methods. But as
far as Ruby is concerned, there’s no special case.

Well Module does have methods private_class_method, and public_class
method, to “make existing class methods” private or public
respectively, so there does seem to be some notion of “class method.”

Array.private_instance_methods

How do I get the private_class_methods?

class << Array; private_instance_methods(false); end

or something along those lines.

Well, you’d think, but not quite:
class <<Array;private_instance_methods(false);end
=> [“inherited”, “initialize”, “initialize_copy”]

Which are the private instance methods of the class Object?!

At least that’s what Object says:

class << Object;private_instance_methods(false);end
=> [“inherited”, “initialize”, “initialize_copy”]

Now perhaps it’s because Array doesn’t HAVE any private class methods,
so lets’ make some test classes:

class A; def A.foo;end; private_class_method :foo;end

class <<A; private_instance_methods(false);end
=> [“inherited”, “foo”, “initialize”, “initialize_copy”]

class B < A;end
class <<B;private_instance_methods(false);end
=> [“inherited”, “foo”, “initialize”, “initialize_copy”]

So for singleton classes of classes, private_instance_methods(false)
is finding the inherited methods, contrary to the specification.

I haven’t sussed out enough of the implementation to figure out why this
is.

This is on 1.8.4 perhaps it’s changed on 1.8.5 but if so it doesn’t
show up in the change log as far as I can tell.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Hi –

On Wed, 30 Aug 2006, Rick DeNatale wrote:

  def foo;end

It’s always struck me as an anomaly. It’s redeemed somewhat by the
superclass thing, whereby class << X is the superclass of class << Y.
(At least, in 1.8.2 and > 1.8.5 it is; I’m not sure why that got
derailed by 1.8.4, since it still behaves that way.)

So was there a change in 1.8.3 which got backed out in 1.8.5?
What was it?

It’s only changed in 1.9, I think (hence “> 1.8.5”). In 1.8.2 you get
this:

rubypal:~$ /usr/local/lib/ruby-1.8.2/bin/irb
irb(main):001:0> class A; end
=> nil
irb(main):002:0> class B < A; end
=> nil
irb(main):003:0> class << A; object_id; end
=> -604523004
irb(main):004:0> class << B; superclass.object_id; end
=> -604523004

I’m not sure about the negative object id numbers… but basically A’s
singleton class is the superclass of B’s singleton class.

In 1.8.4 the numbers are different. But the basic arrangement –
namely, that B can call A’s singleton methods – is still the same.

In recent 1.9’s they’re back to being the same object.

[…]

way of providing a remarkably featureless (I use the word advisedly)
landscape, out of the featurelessness of which one can mold features.
So if you feel like there should be class methods, you can tap into
the fact that class objects can have singleton(ish) methods. But as
far as Ruby is concerned, there’s no special case.

Well Module does have methods private_class_method, and public_class
method, to “make existing class methods” private or public
respectively, so there does seem to be some notion of “class method.”

So it does. Ugh. Oh well :slight_smile: I still tend to see that as layered on
top of what’s really going on.

class <<Array;private_instance_methods(false);end
=> [“inherited”, “initialize”, “initialize_copy”]

Which are the private instance methods of the class Object?!

That also seems to have been a deviation in > 1.8.2 < 1.9:

irb(main):003:0> RUBY_VERSION
=> “1.9.0”
irb(main):004:0> class A; end
=> nil
irb(main):005:0> A.private_instance_methods(false)
=> []

David

On Aug 29, 2006, at 11:09 AM, [email protected] wrote:

way of providing a remarkably featureless (I use the word advisedly)
landscape, out of the featurelessness of which one can mold features.
So if you feel like there should be class methods, you can tap into
the fact that class objects can have singleton(ish) methods. But as
far as Ruby is concerned, there’s no special case.

I totally agree, and I’m sure that has nothing to do with the fact
the Ruby for Rails is what finally crystalized all of this for me.

I really love how that book introduces complex concepts like this so
naturally. Everyone needs to read that book. Period.

Oh, hi David! :wink:

James Edward G. II