Ruby’s Top Self Object

Pat Shaughnessy
Share
Creating functions without a class is
awkward in Smalltalk, but simple in Ruby.

Much of Ruby’s implementation of objects and classes is modeled after Smalltalk, one of the original object oriented languages first built in the late 1960s. Just like with Smalltalk, Ruby’s Object class is the root of your program’s class hierarchy, and all Ruby classes are instances of the Class class. Smalltalk blocks and Ruby blocks also both support using anonymous functions as closures.

But in one interesting way Ruby and Smalltalk differ. Ruby allows you to define simple functions at the top level scope. This enables Ruby to serve as a scripting language. Using Ruby, it’s very easy to combine a few functions together in a small script to accomplish some simple command line task. At the same time, Ruby’s has Smalltalk’s sophisticated OO design at the ready, waiting for you to use it. When your script gets a bit more complex, you can easily turn it into a more organized, object oriented program.

How does Ruby do this? Before your script starts to run, Ruby automatically creates a hidden object known as the top self object, an instance of the Object class. This object serves as the default receiver for top level methods. Today we’ll see how this object – the object we didn’t even know we were using – allows us to write simple functions in an object oriented language.

Functions in Ruby

Using Ruby, you can write functions without creating classes for them. For example, here’s the recursive definition of the factorial function in Ruby.

We were able to write a simple function without thinking about methods, receivers, classes or instance variables. We didn’t need any of these concepts, because all we wanted to do was perform a simple calculation. (Advocates of functional programming, of course, would argue you never need OO concepts – that you can and should write your code exclusively with simple functions.)

In this example, Ruby is not a complex, object oriented language, but just a simple scripting language. For many of us, this is how we started using Ruby: At this level, Ruby’s syntax is very straightforward and easy to learn.

Functions Are Methods

However, under the hood Ruby uses a model similar to Smalltalk. There are no functions in Ruby, only methods. Every method belongs to a class.

But what about my factorial example above? Isn’t that a function? I didn’t declare a class or create an object. I just wrote a simple function. If we display the value of self inside factorial, we’ll see that, in fact, it is a method.

Here you can see Ruby displays the string “main” for the value for self. Because Ruby defines a value for self inside factorial, it must be a method. self contains a reference to the current object, the receiver for the current method. Since factorial has a receiver it must be a method, not a function.

Seeing Ruby’s Top Self Object

The string “main” is how Ruby represents the top self object as a string. Ruby creates it automatically before you program starts in order to serve as the receiver for functions in the top level scope, such as factorial.

In fact, you don’t need to write a method to obtain a value for self. For example:

Here we are running a one line Ruby script using the -e option. You can see puts self returns the string “main.” Another test reveals that the top self object is an instance of Object, the root class of Ruby’s class hierarchy (aside from the internal BasicObject class).

After creating the top self object, Ruby assigns a to_s method to it which returns the string “main.” Ruby does this using C code internally, but it is equivalent to this Ruby snippet:

You can see self is an instance of Object. Also notice Ruby defines this special version of the to_s method only for the top self object. Technically speaking, Ruby creates a singleton class for self and assigns the new to_s method to it. (The default version of to_s, Object#to_s, displays the class name and encoded object id instead.)

Of course, you couldn’t write this code yourself, since self is a reserved word and part of the Ruby language. If you run the code above you’ll get a syntax error “Can’t change the value of self.”

Which Class do Ruby Functions Belong To?

If all Ruby functions are methods, they must belong to some class. But which class? As you might guess, because the top self object is an instance of Object, Ruby adds all top level functions as methods in the Object class. Here’s an example.

Here you can see Ruby’s def keyword saved factorial as a method in the Object class. All Ruby functions are actually private methods of Object. We can prove this is the case by listing the private instance methods of the Object class, like this.

Calling Ruby Functions

Saving functions as Object methods isn’t only to preserve Ruby’s (or Smalltalk’s) elegant object oriented design. Internally, it allows Ruby to find functions when your program calls them. Here’s an example.

At the bottom of the diagram I’ve written a new class called SomeOtherClass. As you can see it contains a single method show_the_answer which calls the factorial function.

When I call factorial, Ruby first looks to see if factorial is a method of SomeOtherClass. Because it isn’t, Ruby then looks through the superclasses of SomeOtherClass to find factorial. Because Ruby added the factorial function to Object, the class of the top self object, Ruby will find it since Object is a superclass of every other class.

Ruby’s Hidden Object

This might seem like a bit of syntactic sugar. Why does it matter which class Ruby uses to save functions? It fact, does it even matter that functions are methods? They work the same way. And why does the value of self in the top lexical scope matter?

The key point here is that this trick allows you to write simple functions in Ruby. If we weren’t able to write them, Ruby would be harder to learn and more awkward to use. You would have to understand object oriented programming ideas even to get started writing the simplest script using Ruby.

Because it’s hidden, because we don’t know we’re using it, the top self object allows us to use Ruby without object and classes as a simple scripting language. Ruby is much easier to learn than Smalltalk because of the top self object. To learn more about Ruby’s method lookup algorithm, how Ruby implements objects, classes, lexical scope and much more, look for the updated version of my book Ruby Under a Microscope, due out in November from No Starch Press.

CSS Master, 3rd Edition