You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit b87a588
Browse filesBrowse the repository at this point in the historyBrowse files
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>
Copy file name to clipboardExpand all lines: docs/_posts/2006-07-22-from-singleton-to-legion.md
+17-7Lines changed: 17 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,9 +1,19 @@
1
1
---
2
2
title: From Singleton to Legion
3
3
date: 2006-07-22
4
-
published: false
5
4
---
6
5
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
+
7
17
<!-- ---
8
18
title: From Singleton to Legion
9
19
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
15
25
16
26
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.
17
27
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?
19
29
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.
21
31
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:
23
33
24
34
```ruby
25
35
o =Object.new
@@ -32,8 +42,8 @@ end
32
42
o.x => "xx"
33
43
```
34
44
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.
36
46
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.
38
48
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" ;)
Copy file name to clipboardExpand all lines: docs/_posts/2006-08-17-main-is-a-dry-pain.md
+18-4Lines changed: 18 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,9 +1,23 @@
1
1
---
2
2
title: Main is a DRY Pain
3
3
date: 2006-08-17
4
-
published: false
5
4
---
6
5
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
+
7
21
<!-- ---
8
22
title: Main is a DRY Pain
9
23
date: "2006-08-17"
@@ -19,7 +33,7 @@ That seems fairly peculiar when you consider that defining methods at toplevel i
19
33
self#=> main
20
34
```
21
35
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:
23
37
24
38
```ruby
25
39
self.class#=> Object
@@ -46,7 +60,7 @@ class Q
46
60
end
47
61
48
62
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>
50
64
```
51
65
52
66
Which means the sure solution for my problem...
@@ -79,6 +93,6 @@ Q.new.q
79
93
#=> NameError: undefined local variable or method `m' for #<Q:0xb7cbb324>
80
94
```
81
95
82
-
Lands me squre in the face of the Module Inclusion Problem.
96
+
Lands me square in the face of the Module Inclusion Problem.
83
97
84
98
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?
Copy file name to clipboardExpand all lines: docs/_posts/2006-08-18-vote-kernel-for-toplevel-object.md
+18-6Lines changed: 18 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,15 +1,27 @@
1
1
---
2
2
title: Vote Kernel for Toplevel Object
3
3
date: 2006-08-18
4
-
published: false
5
4
---
6
5
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
+
7
19
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:
8
20
9
21
matz: Why? If it is really required it's fairly
10
22
easy to add toplevel methods like we did for #include.
11
23
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:
13
25
14
26
```ruby
15
27
moduleQ
@@ -50,9 +62,9 @@ true
50
62
false
51
63
```
52
64
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.
54
66
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.
56
68
57
69
```ruby
58
70
moduleMain
@@ -61,15 +73,15 @@ module Main
61
73
end
62
74
```
63
75
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.
65
77
66
78
```ruby
67
79
classObject
68
80
includeMain
69
81
end
70
82
```
71
83
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:
0 commit comments