[ANN] Article: Seeing Metaclasses Clearly

I've written a very nuts+bolts article on metaclasses (aka virtual classes or metaobjects), since they still lurk under a shroud of fear and enigma.

<http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html>

I'm hoping this will help uncover the truth. If anything is unclear, please report it. Shed a light.

Sharkin',

_why

why the lucky stiff wrote:

I've written a very nuts+bolts article on metaclasses (aka virtual classes or metaobjects), since they still lurk under a shroud of fear and enigma.

<http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&gt;

I'm hoping this will help uncover the truth. If anything is unclear, please report it. Shed a light.

Very nice and thanks,

would you mind using a print stylesheet so the article can be nicely printed out?

Sascha Ebach

Hi --

I've written a very nuts+bolts article on metaclasses (aka virtual classes or metaobjects), since they still lurk under a shroud of fear and enigma.

<http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&gt;

I'm hoping this will help uncover the truth. If anything is unclear, please report it. Shed a light.

For some reason the first 1/8 inch or so on the left are cut off on my
browser. I don't know whether it's a CSS thing or a browser thing
(Netscape 6). So "methods" comes out as "thods", etc.

The tutorial itself looks good, though the terminology in this area
continues to be a problem. My understanding is that the most general
term is "singleton class", and that "metaclass" is a special term for
singleton class of a Class object. (See Pickaxe, 2nd ed., p. 382.)
So, for example, I would rename your Object#metaclass method
#singleton_class, since it applies to all objects (as per RCR 231).

Then there's "virtual class", which I think is the weakest and least
useful term, certainly at a general level. The Matz paraphrase on
p.382 suggests that virtual-ness is more a matter of implementation
than anything language-level, which is good. I haven't checked, but
I'm hoping the > 1.8 error messages will cease to refer to "virtual"
classes (e.g., when you try to get at the singleton class of a
Fixnum).

David

···

On Mon, 18 Apr 2005, why the lucky stiff wrote:

--
David A. Black
dblack@wobblini.net

why the lucky stiff wrote:

<http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&gt;

I'm hoping this will help uncover the truth. If anything is unclear, please report it. Shed a light.

Nice article, but I disagree in the point that @@vars are simpler than class instance variables. Class instance variables have odd semantics in the current Ruby which means that they will probably do some detail different than you expect.

I've found that sticking to class instance variables (and thus keeping things simple -- why do we need another type of variables again?) helps in making code easier to understand.

Perhaps you should display both sides of this in the article.

why the lucky stiff wrote:

I've written a very nuts+bolts article on metaclasses (aka virtual
classes or metaobjects), since they still lurk under a shroud of fear

and enigma.

<http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&gt;

I'm hoping this will help uncover the truth. If anything is unclear,

please report it. Shed a light.

Noticed a small mistake; At one point, you refer to the at-sign (@) as
an ampersand. Other than that... the article went way over my head and
twisted my poor brain into knots. :frowning: I think I'll need to re-read
chapter 24 of Pickaxe 2 immediately before reading this article.

why the lucky stiff wrote:

I've written a very nuts+bolts article on metaclasses (aka virtual classes or metaobjects), since they still lurk under a shroud of fear and enigma.

<http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&gt;

I'm hoping this will help uncover the truth. If anything is unclear, please report it. Shed a light.

One thing I found confusing was the comment for the class_def method

># Just defines a class method
>def class_def name, &blk
> class_eval { define_method name, &blk }
>end

However it actually defines an instance method

require "metaid"

class MyClass
   class_def "class_method" do puts "success" end
end

MyClass.class_method
   #=> undefined method "class_method" for MyClass:Class

MyClass.new.class_method #=> success

···

--
Mark Sparshatt

_why,

Nice tutorial, I found I learned something from it. I know there is a chapter in the pickaxe that attempts to explain this, but this seems to be the best (only?) freely available explanation.

Being somewhat new to the concept of metaprogramming, I can tell you what is particularly confusing is the use of class << self, how this is like the root of all singleton behavior, how it differs from class a < b (perhaps even display how it works inside the interpreter). I wasn't sure what the difference between the < and the << operator was, so I had to go look it up.

Also the difference between class instance variables and class variables could use some extra explaining, it seems you're just saying what to do and what not to do, but not why you can't or shouldn't do it, and why a @@ class variable is handy.

Thanks,

-Jeff

···

----- Original Message ----- From: "why the lucky stiff" <ruby-talk@whytheluckystiff.net>
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Sent: Monday, April 18, 2005 12:50 AM
Subject: [ANN] Article: Seeing Metaclasses Clearly

I've written a very nuts+bolts article on metaclasses (aka virtual classes or metaobjects), since they still lurk under a shroud of fear and enigma.

<http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&gt;

I'm hoping this will help uncover the truth. If anything is unclear, please report it. Shed a light.

Sharkin',

_why

why the lucky stiff a écrit :

I've written a very nuts+bolts article on metaclasses (aka virtual classes or metaobjects), since they still lurk under a shroud of fear and enigma.

<http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&gt;

I'm hoping this will help uncover the truth. If anything is unclear, please report it. Shed a light.

Sharkin',

_why

Errata

In the begining of the page:
"I’ve been keeping these methods in a file called metaid.rb and it’s a start toward building a little library that can simplify use of metaclasses. Let’s talk about metaclasses and I advise you to keep metaid.rb at your side. Let’s talk about metaclasses and I advise you to keep metaid.rb at your side."

"Let’s talk about metaclasses and I advise you to keep metaid.rb at your side." is said twice.

···

--
Lionel Thiry

Personal website: http://users.skynet.be/lthiry/

From the article

"It's an important lesson: objects do not store methods, only classes can."

Might be nice to contrast this with prototype based languages like javascript.

Or ProtoRuby :wink:

class ProtoObj
  def initialize
    @methods = {}
  end
  def addMethod(name, &method)
    @methods[name.id2name] = method
  end
  def method_missing(method, *args)
    @methods[method.id2name].call(*args)
  end
end

dog = ProtoObj.new
dog.addMethod(:bark) {
  puts "Bark"
}
dog.bark

But you have to do:

class Foo
  @var1 =
  @var2 = {}
  class << self
    attr_accessor :var1, :var2
  end
end

to get reasonable access to those class instance variables inside an instance method, and even then you have to do self.class.var1

Once you 'get it' it's not TERRIBLY difficult, but I would say that the above is more than enough justification for calling @@foo simpler. Simpler, but also confusing in the inherited-class cases. (So confusing that I still don't fully grok what specifically occurs that makes @@foo unusable, and when it occurs. I'm still grasping at the fringes of the tablecloth.)

···

On Apr 18, 2005, at 6:33 AM, Florian Groß wrote:

Nice article, but I disagree in the point that @@vars are simpler than class instance variables. Class instance variables have odd semantics in the current Ruby which means that they will probably do some detail different than you expect.

Florian Groß wrote:

Nice article, but I disagree in the point that @@vars are simpler than class instance variables. Class instance variables have odd semantics in the current Ruby which means that they will probably do some detail different than you expect.

You're right. I'm oversimplifying this. I need to discuss the metaclass/inheritance thing a bit more.

_why

David A. Black wrote:

Hi --

I've written a very nuts+bolts article on metaclasses (aka virtual classes or
metaobjects), since they still lurk under a shroud of fear and enigma.

<http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&gt;

I'm hoping this will help uncover the truth. If anything is unclear, please
report it. Shed a light.

For some reason the first 1/8 inch or so on the left are cut off on my
browser. I don't know whether it's a CSS thing or a browser thing
(Netscape 6). So "methods" comes out as "thods", etc.

Also, in Firefox 1.0 on Windows XP, when I try to print it, it only prints the first page. If I use MS Internet Explorer, it prints just fine.

Curt

···

On Mon, 18 Apr 2005, why the lucky stiff wrote:

David A. Black wrote:

The tutorial itself looks good, though the terminology in this area
continues to be a problem. My understanding is that the most general
term is "singleton class", and that "metaclass" is a special term for
singleton class of a Class object. (See Pickaxe, 2nd ed., p. 382.)
So, for example, I would rename your Object#metaclass method
#singleton_class, since it applies to all objects (as per RCR 231).

Sure, I'm aware that "virtual class" is the generic term, while Matz has also used "singleton class" and "meta-object" to describe these classes used in tandem with an RObject.

I only use the term "metaclass" because it is the term predominantly used in the PickAxe II. While Dave does interchangibly use "virtual class" and "singleton class", the only term he uses to generically refer to the construct is "metaclass".

And I really need to be able to wrap these up in a single word, whilst still jiving with the PickAxe.

_why

Karl von Laudermann wrote:

why the lucky stiff wrote:
> I've written a very nuts+bolts article on metaclasses (aka virtual
> classes or metaobjects), since they still lurk under a shroud of

fear

> and enigma.
>
>

<http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&gt;

>
> I'm hoping this will help uncover the truth. If anything is

unclear,

> please report it. Shed a light.

Noticed a small mistake; At one point, you refer to the at-sign (@)

as

an ampersand. Other than that... the article went way over my head

and

twisted my poor brain into knots. :frowning: I think I'll need to re-read
chapter 24 of Pickaxe 2 immediately before reading this article.

Glad I'm not the only one who has to go back to the books! (I did spot
the "ampersand" thing, though).

"Florian Groß" <florgro@gmail.com> schrieb im Newsbeitrag
news:d4093s$dml$1@sea.gmane.org...

why the lucky stiff wrote:

> <http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&gt;
>
> I'm hoping this will help uncover the truth. If anything is unclear,
> please report it. Shed a light.

Nice article, but I disagree in the point that @@vars are simpler than
class instance variables. Class instance variables have odd semantics in
the current Ruby which means that they will probably do some detail
different than you expect.

I've found that sticking to class instance variables (and thus keeping
things simple -- why do we need another type of variables again?) helps
in making code easier to understand.

+1

Perhaps you should display both sides of this in the article.

Yeah, I missed that, too. In fact, the article seems to discourage class
instance variable usage...

Kind regards

    robert

mark sparshatt a écrit :

why the lucky stiff wrote:

I've written a very nuts+bolts article on metaclasses (aka virtual classes or metaobjects), since they still lurk under a shroud of fear and enigma.

<http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&gt;

I'm hoping this will help uncover the truth. If anything is unclear, please report it. Shed a light.

One thing I found confusing was the comment for the class_def method

># Just defines a class method
>def class_def name, &blk
> class_eval { define_method name, &blk }
>end

However it actually defines an instance method

require "metaid"

class MyClass
  class_def "class_method" do puts "success" end
end

MyClass.class_method
  #=> undefined method "class_method" for MyClass:Class

MyClass.new.class_method #=> success

The only I've found to make your sample code work is to refactor class_def this way:
  def class_def name, &blk
   meta_eval { define_method name, &blk }
  end

I personnaly feel it weird I could not realise this whithout the help of the metaclass manipulation methods _why has added.

···

--
Lionel Thiry

Jeffrey Moss wrote:

Being somewhat new to the concept of metaprogramming, I can tell you what is particularly confusing is the use of class << self, how this is like the root of all singleton behavior, how it differs from class a < b (perhaps even display how it works inside the interpreter). I wasn't sure what the difference between the < and the << operator was, so I had to go look it up.

My article briefly discusses the singleton class notation (the << you are referring to). This notation is very simple to understand once you've gotten the hang of:

1. Objects are containers for instance variables.
2. Classes are containers for methods and instance variables.

There are more to objects and classes than this, but for the sake of this discussion, it's useful to whittle it down to this.

  a = Object.new
  a.instance_variable_set( "@name", "Jeff" )

I've created a new object above, storage for instance variables. I've added an instance variable to the object. In doing so, I called the `instance_variable_set' method. This method isn't contained in the `a' object. It's contained way up the inheritance tree, in the Object class.

Again: the instance variables are stored in the object. The methods are stored in a class up the inheritance tree.

   class << a
     def name; @name; end
   end

We're opening a metaclass here. What is a metaclass? It's method storage for an object. An object can only store instance variables. The `name' method has been added to the metaclass (the personal method storage) for the object `a'.

The most needlessly confusing construct in Ruby is `class << self'. You're simply accessing the method storage for whatever object is currently `self'.

  class Dragon
    class << self; p self; end
  end

Prints: #<Class:Dragon>

Okay, so we're in the metaclass for a class. But what is that?

It's method storage for class methods. Normal instance methods are stored directly in the class. But class methods are stored in the metaclass.

  class Dragon
    def self.me; p self; end # This method is stored in the metaclass
    def me; p self; end # This method is stored in the class
  end

  Dragon.me #=> Dragon
  Dragon.new.me #=> #<Dragon:0x80914e0>

Everyone who uses class methods uses metaclasses.

  class << Dragon
     def roar; "#<CLASS:ROAR>"; end
  end
  Dragon.roar #=> #<CLASS:ROAR>

  d = Dragon.new
  class << d
    def roar; "#<OBJ:ROAR>"; end
  end
  d.roar #=> #<OBJ:ROAR>

I don't really get into this in the article, since I've opted to use the `metaclass' method and `meta_eval' which are alternate forms of the above.

The < operator is a completely different operator, used strictly for setting the superclass of a class.

But one handy thing about metaclass (which I believe qualifies them for the meta- prefix) is that they follow the inheritance tree, simply remaining one level removed.

  >> Dragon.metaclass
  => #<Class:Dragon>
  >> Dragon.metaclass.superclass
  => #<Class:Object>
  >> Dragon.superclass.metaclass
  => #<Class:Object>

See, an object's metaclass' superclass is the same as the object's superclass' metaclass.

Also the difference between class instance variables and class variables could use some extra explaining, it seems you're just saying what to do and what not to do, but not why you can't or shouldn't do it, and why a @@ class variable is handy.

I'll address this once I'm sure I completely understand variable.c and have played around with class variables in metaclasses a bit more.

_why

That happens to me when I try and print my bank statements, its probably a firefox bug.

-Jeff

···

Also, in Firefox 1.0 on Windows XP, when I try to print it, it only prints the first page. If I use MS Internet Explorer, it prints just fine.

Curt

Lionel Thiry wrote:

The only I've found to make your sample code work is to refactor class_def this way:
def class_def name, &blk
  meta_eval { define_method name, &blk }
end

That's the `meta_def' you've recreated above.

The `class_def' method is intended to be used to add instance methods (like the `initialize' I'm adding in Dwemthy's Array):

  class Dragon; end
  Dragon.class_def :initialize do
     @life = 11; @strength = 12
  end

  >> d = Dragon.new
  => #<Dragon:0xb7d571e8 @strength=12, @life=11>

The `meta_def' can be used to add class methods, because of reasons stated throughout the article and in my response to Jeff.

_why

Hi --

David A. Black wrote:

The tutorial itself looks good, though the terminology in this area
continues to be a problem. My understanding is that the most general
term is "singleton class", and that "metaclass" is a special term for
singleton class of a Class object. (See Pickaxe, 2nd ed., p. 382.)
So, for example, I would rename your Object#metaclass method
#singleton_class, since it applies to all objects (as per RCR 231).

Sure, I'm aware that "virtual class" is the generic term, while Matz has also used "singleton class" and "meta-object" to describe these classes used in tandem with an RObject.

I only use the term "metaclass" because it is the term predominantly used in the PickAxe II. While Dave does interchangibly use "virtual class" and "singleton class", the only term he uses to generically refer to the construct is "metaclass".

And I really need to be able to wrap these up in a single word, whilst still jiving with the PickAxe.

I read the Pickaxe differently, especially the box on p. 382. It
paraphrases Matz as having said: "You can call it _metaclass_ but,
unlike Smalltalk, it's not a class of a class; it's a singleton class
of a class."

I don't think there's any case where Dave refers to a singleton class
as a metaclass, except where the object is a Class, but I could be
wrong about that... ?

Anyway, when RCR 231 gets addressed, we'll find out for sure :slight_smile:

(I think I misread the p. 382 thing about "virtual". It does actually
sound like Matz is accepting it as a synonym for "singleton", though I
avoid it because I don't see anything "virtual" about singleton
classes. They're objects.)

David

···

On Mon, 18 Apr 2005, why the lucky stiff wrote:

--
David A. Black
dblack@wobblini.net