Skip to content

Commit b87a588

Browse files
transclaude
andcommitted
Publish 18 more imported blog posts :doc:
Each now opens with a dated note on what has changed in Ruby or Facets since it was written, and has its typos, broken code samples and dead links fixed. Links between posts use post_url, so they also work in the feed. Three stay unpublished because they still read as drafts: "The Meaninglessness of Class vs Module", "We Don't Need no Stinking Modules" and "Proper Construction of a Class". Their fixes are included, but the drafts need the author's decision before they go out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 8913507 commit b87a588

21 files changed

Lines changed: 289 additions & 160 deletions

‎docs/_posts/2006-07-22-from-singleton-to-legion.md‎

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
---
22
title: From Singleton to Legion
33
date: 2006-07-22
4-
published: false
54
---
65

6+
> **Update, November 2026:** Ruby 1.9.2 added `Kernel#singleton_class`,
7+
> which made "singleton class" the official name. Ruby still keeps a single
8+
> singleton class per object, so on an unpatched Ruby the second `def o.x`
9+
> below replaces the first, and its `super` raises `NoMethodError`. But
10+
> Ruby 2.0 added `Module#prepend`, and prepending a module to the singleton
11+
> class gives much the same layering: after
12+
> `o.singleton_class.prepend(Module.new { def x; super + "x"; end })`,
13+
> `o.x` returns `"xx"`. Facets carried both `eigenclass` and `qua_class` as
14+
> `Kernel` methods. Facets 3.2 deprecated them in favor of `singleton_class`
15+
> or Facets' `meta_class`, and they will be removed after 2027-09-30.
16+
717
<!-- ---
818
title: From Singleton to Legion
919
date: "2016-07-22"
@@ -15,11 +25,11 @@ For as long as I've coded Ruby there has been some question as to the appropriat
1525

1626
While the term is fitting in the sense that each object only has one of these classes (hence "single"), issues arise from a terminology clash with an already well accepted object-oriented programming term, [Singleton Pattern](http://en.wikipedia.org/wiki/Singleton_pattern). In OOP-speak a singleton class is a class that can only be instantiated once. Many have argued that the Singleton pattern itself is a flawed concept, since one can just instantiate an object and assign it to a constant to achieve the same end. So why restrict anyone from a second instance of a class if they so choose? That's a reasonable argument, although not always as practical as it might seem. Nonetheless, the terminology clash still remains.
1727

18-
In light of nomenclature issue, many have offered alternative terms for Ruby's singleton class. Indeed, Ruby itself has used two alternatives in the past: virtual class and metaclass, and many people still prefer that later of these choices. Other suggestions include the well known _whyism `eigenclass`, the abbreviated `sclass`, the pronoun contingents 'myclass' and 'ownclass', as well as my own concoctions `adhoc` and `qua_class`. Yet despite all these names, none of which ever stick, what is this singly thing really?
28+
In light of nomenclature issue, many have offered alternative terms for Ruby's singleton class. Indeed, Ruby itself has used two alternatives in the past: virtual class and metaclass, and many people still prefer the latter of these choices. Other suggestions include the well known _whyism `eigenclass`, the abbreviated `sclass`, the pronoun contingents 'myclass' and 'ownclass', as well as my own concoctions `adhoc` and `qua_class`. Yet despite all these names, none of which ever stick, what is this singly thing really?
1929

20-
Recently, our beloved Pit Capitan put it concisely when he said "there are only two types of methods in Ruby, instance methods and singleton methods". Well said. Unfortunately it's not quite true. Instance methods aren't really methods at all, they are just definitions for methods to be. That's why when you use `#instance_method` you get something called an `UnboundMethod`, not a `Method`. It only becomes a method when it's bound to an object. To clarify further how that distinction is a bit misleading, consider that when a singleton method is defined it falls into an inheritance hierarchy along side so-called instance methods. In other words, the singleton methods and instance methods exist on the same playing field, and the former can call on the other via `#super`. In fact, we can access these singleton methods in instance fashion via `(class<<obj;self;end).instance_method(sym)`. So these methods are not really distinct in this manner after all. In fact there is no distinction between methods other than bound and unbound. And this distinction arises from the capability of class Module and class Class to harbor a set of method definitions that are not their own. Which is of course exactly why these constructs exist in the first place. So when we say singleton method, we are not referring to something different from instance method. We only mean that these methods are kept in a special "singleton class", made just for a specific object, and consequently, are automatically bound to that object.
30+
Recently, our beloved Pit Capitain put it concisely when he said "there are only two types of methods in Ruby, instance methods and singleton methods". Well said. Unfortunately it's not quite true. Instance methods aren't really methods at all, they are just definitions for methods to be. That's why when you use `#instance_method` you get something called an `UnboundMethod`, not a `Method`. It only becomes a method when it's bound to an object. To clarify further how that distinction is a bit misleading, consider that when a singleton method is defined it falls into an inheritance hierarchy alongside so-called instance methods. In other words, the singleton methods and instance methods exist on the same playing field, and the former can call on the other via `#super`. In fact, we can access these singleton methods in instance fashion via `(class<<obj;self;end).instance_method(sym)`. So these methods are not really distinct in this manner after all. In fact there is no distinction between methods other than bound and unbound. And this distinction arises from the capability of class Module and class Class to harbor a set of method definitions that are not their own. Which is of course exactly why these constructs exist in the first place. So when we say singleton method, we are not referring to something different from instance method. We only mean that these methods are kept in a special "singleton class", made just for a specific object, and consequently, are automatically bound to that object.
2131

22-
Now, I'm going to claim that the term 'singleton' is a poor choice for a completely different reason than any given before. It may come as a bit of surprise, but singletons are not inherently single. They are only made so by an explicit restriction in the Ruby's source code. It is quite simple, actually, to remark-out the if-clause from the source, recompile Ruby and then do:
32+
Now, I'm going to claim that the term 'singleton' is a poor choice for a completely different reason than any given before. It may come as a bit of surprise, but singletons are not inherently single. They are only made so by an explicit restriction in Ruby's source code. It is quite simple, actually, to remark-out the if-clause from the source, recompile Ruby and then do:
2333

2434
```ruby
2535
o = Object.new
@@ -32,8 +42,8 @@ end
3242
o.x => "xx"
3343
```
3444

35-
The reason Ruby makes the per-object classes single is because it would be terribly inefficient to define a whole new class for every new singleton method defined. That's understandable, but it also comes at a cost. We can not reliably receive an object from the outside world and define our own singleton on it because we may be clobbering someone else's singleton method without even knowing it. (NOTE: It doesn't matter so much if you're just redefining a method altogether, but if you're calling super it very much matters.) Generally we don't even think about such things, but truth be told, object singleton methods often fail to survive code refactoring. Object singleton's really only exist as a side effect of Ruby's class model (and Smalltalk's?) which utilize the singleton class as a means of separating a module/class method definitions from it's own actual methods. This could have been done another way of course, but then a class/module would be something wholly different from any other object. The use of the singleton allowed classes and modules to be just like any other object. So singletons are really a bit of cleverness that lie at the very heart of how Ruby works.
45+
The reason Ruby makes the per-object classes single is because it would be terribly inefficient to define a whole new class for every new singleton method defined. That's understandable, but it also comes at a cost. We can not reliably receive an object from the outside world and define our own singleton on it because we may be clobbering someone else's singleton method without even knowing it. (NOTE: It doesn't matter so much if you're just redefining a method altogether, but if you're calling super it very much matters.) Generally we don't even think about such things, but truth be told, object singleton methods often fail to survive code refactoring. Object singletons really only exist as a side effect of Ruby's class model (and Smalltalk's?) which utilize the singleton class as a means of separating a module/class method definitions from its own actual methods. This could have been done another way of course, but then a class/module would be something wholly different from any other object. The use of the singleton allowed classes and modules to be just like any other object. So singletons are really a bit of cleverness that lie at the very heart of how Ruby works.
3646

37-
Does it mean that they have to be singly? Could we remove the restriction and open up a additional robustness to these per-object classes? We could. In fact, this was the very first hack I ever made to the Ruby source code. My change simply checked to see if the method was already defined in the first "singleton" layer and continue upward until it either found a usable layer or ran out of layers, in which case it created a new one. Combined with the capability to selectively undefine particular methods of particular layers and we gain a flexible pre-object class hierarchy system that can be used without the caveats that currently make singletons so limited outside of class and module definitions.
47+
Does it mean that they have to be singly? Could we remove the restriction and open up an additional robustness to these per-object classes? We could. In fact, this was the very first hack I ever made to the Ruby source code. My change simply checked to see if the method was already defined in the first "singleton" layer and continue upward until it either found a usable layer or ran out of layers, in which case it created a new one. Combined with the capability to selectively undefine particular methods of particular layers and we gain a flexible per-object class hierarchy system that can be used without the caveats that currently make singletons so limited outside of class and module definitions.
3848

39-
And then we no long can call them "singleton" but rather "legion" ;)
49+
And then we no longer can call them "singleton" but rather "legion" ;)

‎docs/_posts/2006-08-17-main-is-a-dry-pain.md‎

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
---
22
title: Main is a DRY Pain
33
date: 2006-08-17
4-
published: false
54
---
65

6+
> **Update, November 2026:** Ruby 2.0 gave `main` a `define_method` of its
7+
> own, which defines a method on `Object`, so the first error below no
8+
> longer happens, though `main` still has no `ancestors`. Ruby 2.0 also
9+
> made `main`'s `include`, `public` and `private` private methods, so on
10+
> Ruby 3.4 the `public_methods` comparison below returns `[]`, and
11+
> `singleton_methods` returns only `[:to_s, :inspect]`. Ruby 3.0 fixed the
12+
> Module Inclusion Problem ([#9573](https://bugs.ruby-lang.org/issues/9573)):
13+
> a module included into `Kernel` now reaches every object, so in the last
14+
> example both `m` and `Q.new.q` return `"m"`. Methods defined in `main`'s
15+
> singleton class are still not visible anywhere else, as the `class << self`
16+
> example shows. I've corrected the method name in that example's error
17+
> message, which said `s`. I took up the question of `main` as a
18+
> self-extended module again in
19+
> [Kill the Proxy and Save Toplevel]({{ site.baseurl }}{% post_url 2012-06-17-kill-the-proxy-and-save-toplevel %}).
20+
721
<!-- ---
822
title: Main is a DRY Pain
923
date: "2006-08-17"
@@ -19,7 +33,7 @@ That seems fairly peculiar when you consider that defining methods at toplevel i
1933
self #=> main
2034
```
2135

22-
Okay, it calls itself "main". Great. But that doesn't really tell us anything. Let's check it's class:
36+
Okay, it calls itself "main". Great. But that doesn't really tell us anything. Let's check its class:
2337

2438
```ruby
2539
self.class #=> Object
@@ -46,7 +60,7 @@ class Q
4660
end
4761

4862
Q.new.q
49-
#=> NameError: undefined local variable or method 's' for #<Q:0xb7ce9a3c>
63+
#=> NameError: undefined local variable or method `x' for #<Q:0xb7ce9a3c>
5064
```
5165

5266
Which means the sure solution for my problem...
@@ -79,6 +93,6 @@ Q.new.q
7993
#=> NameError: undefined local variable or method `m' for #<Q:0xb7cbb324>
8094
```
8195

82-
Lands me squre in the face of the Module Inclusion Problem.
96+
Lands me square in the face of the Module Inclusion Problem.
8397

8498
All this leads me to two points. First, I'm stuck! There seems to be no solution to my problem other than rewriting a second version of my module specifically for the toplevel. Talk about lack of DRY! And 2) Why in the world isn't main a self extended module?

‎docs/_posts/2006-08-18-vote-kernel-for-toplevel-object.md‎

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
---
22
title: Vote Kernel for Toplevel Object
33
date: 2006-08-18
4-
published: false
54
---
65

6+
> **Update, November 2026:** Ruby 2.0 added the kind of top-level method
7+
> matz mentions below: `main` now has its own private `define_method`,
8+
> which defines methods on `Object`. Because `main` finds its own
9+
> `define_method` first, the example below never calls the hand-written one.
10+
> It still prints `true` and `false`, though, because `main` is still not
11+
> `Object`. Taskable didn't last in
12+
> Facets: by version 1.8 (January 2007), taskable.rb had been dropped
13+
> because its "implementation won't work as toplevel include". For a while
14+
> Facets also had main_as_module.rb (later main.rb), which made `main` act
15+
> more like a module; Facets 2.9.3 spun it off as the main_like_module gem.
16+
> Ruby's top level is still not a module. I took up the idea again in
17+
> [Kill the Proxy and Save Toplevel]({{ site.baseurl }}{% post_url 2012-06-17-kill-the-proxy-and-save-toplevel %}).
18+
719
As a follow up to my last post on the "pain that is main", I want to offer a potential improvement for Ruby 2.0. I approached the topic on ruby-talk this week and while Matz initially took some interest, he hasn't followed up since his last comment:
820

921
matz: Why? If it is really required it's fairly
1022
easy to add toplevel methods like we did for #include.
1123

12-
But it isn't always easy. In order get my Taskable module to work, for instance, I had to make exceptions for the toplevel case, which is far from ideal and is fragile [Ed- in fact I'm still getting bugs that I haven't yet pinned down]. These subtile difficulties arise becuase main acts as a partial proxy for the Object class. Anyone who has created a proxy object before knows the subtile issues that can come into play. In this case, only the bare minimal interface is supported --essentially the method #include. Yet, even if we take matz' advice and add in all the missing proxy methods, we still won't be 100% out of the woods. The Object class and main are fundamentally two distinct objects --self is not the same, nor are their singleton classes, &c. In the vast majority of cases this will never present an issue, but the distinction can creep in. Here's an highlight of one way it can:
24+
But it isn't always easy. In order to get my Taskable module to work, for instance, I had to make exceptions for the toplevel case, which is far from ideal and is fragile [Ed- in fact I'm still getting bugs that I haven't yet pinned down]. These subtle difficulties arise because main acts as a partial proxy for the Object class. Anyone who has created a proxy object before knows the subtle issues that can come into play. In this case, only the bare minimal interface is supported --essentially the method #include. Yet, even if we take matz' advice and add in all the missing proxy methods, we still won't be 100% out of the woods. The Object class and main are fundamentally two distinct objects --self is not the same, nor are their singleton classes, &c. In the vast majority of cases this will never present an issue, but the distinction can creep in. Here's a highlight of one way it can:
1325

1426
```ruby
1527
module Q
@@ -50,9 +62,9 @@ true
5062
false
5163
```
5264

53-
So in effect Ruby is mildly schizophrenic. The false reading is because main != Object. So, you can't necessarily create a DSL for Object to be used in main, and you can't neccessairly create a DSL for main to be used in any Object. Hence the devolution to DRYless code.
65+
So in effect Ruby is mildly schizophrenic. The false reading is because main != Object. So, you can't necessarily create a DSL for Object to be used in main, and you can't necessarily create a DSL for main to be used in any Object. Hence the devolution to DRYless code.
5466

55-
There is a potentially elegant solution however, and I'd really like to understand others insights into this (especially Matz' of course): Instead of main being a special proxy object, just let it be a self extended module.
67+
There is a potentially elegant solution however, and I'd really like to understand others' insights into this (especially Matz' of course): Instead of main being a special proxy object, just let it be a self extended module.
5668

5769
```ruby
5870
module Main
@@ -61,15 +73,15 @@ module Main
6173
end
6274
```
6375

64-
This would provide all the facilities required of the toplevel without all the proxy troubles. Also, while I'm not so convinced of the merits of every toplevel method becoming a private method of all objects (and with Main that can be easily prevented), it has proven workable in practice so it's not a significant factor of consideration here. Main can simply be include in Object to achieve that effect.
76+
This would provide all the facilities required of the toplevel without all the proxy troubles. Also, while I'm not so convinced of the merits of every toplevel method becoming a private method of all objects (and with Main that can be easily prevented), it has proven workable in practice so it's not a significant factor of consideration here. Main can simply be included in Object to achieve that effect.
6577

6678
```ruby
6779
class Object
6880
include Main
6981
end
7082
```
7183

72-
But when we do that it becomes very clear what Main appears to be: Kernel. That strikes me as esspecially interesting. Then again, there may be good reasons to keep the Kernel as a separate module, in which case we'd just have a class hierachy:
84+
But when we do that it becomes very clear what Main appears to be: Kernel. That strikes me as especially interesting. Then again, there may be good reasons to keep the Kernel as a separate module, in which case we'd just have a class hierarchy:
7385

7486
```ruby
7587
Object.ancestors

0 commit comments

Comments
 (0)