For many beginning Rubyists, especially those having experience in other programming languages such as Java or C, checking whether variable is nil may seem a little bit confusing. And even those speaking Ruby quite fluently don’t usually know the tiny little details that stand behind the nil object.

NilClass and Nil Object

In Ruby, there are no primitives. I don’t mean people hunting for mammoths and living in caves, I mean primitive types. That is, there is no distinction between simple variables (like numbers) and more complicated ones. They all have one common ancestor, the Object class. 5 is an object and hash is an object, too. Everything is an object.

Former Java or C programmers are used to treat NULL as a special value or even a keyword. In these languages, NULL holds a value that no valid pointer will ever refer to. So, to check whether object is nil (NULL), one should compare it with the special NULL value:

// Java code
//
if (myObject != null) {
  myObject.displayInfo();
} else {
  System.out.println("There is no object!");
}

As you can see, programmer needs to make sure first that the object really exists, i.e. it points to something different than null. Calling methods on a null object causes the NullPointerException to be thrown. In C, operating on invalid pointer may lead to unexpected results.

As you may expect, there should be a Ruby way to check if object is nil. Here it is:

# Ruby code
#
if my_object.nil?
  puts "There is no object!"
else
  my_object.display_info()
end

Wait a second… What we’ve actually done to check if object is nil, was to call the nil? method. Calling a method on a not existing object? Isn’t it any kind of trap?

No, it is not. As I’ve already said, in Ruby every value is an object. So, nil is an object, too. In fact, it is an instance of the NilClass:

> nil.class
=> NilClass

Moreover, nil is always equal to nil:

> nil == nil
=> true

Theoretically, nil values should be incomparable, just like it is in SQL. But for practical reasons and to spare memory, nil object was made a singleton. That is, there is always exactly one instance of the NilClass which can be simply referred to by typing nil.

To keep things consistent, the nil? method has been moved to the very top of the object tree - to the Object class. Having that in mind, you can call this method on any object you want and it will return a result rather than cause the NoMethodError to be raised:

> 5.nil?
=> false

> [1, 2, 3].nil?
=> false

> {:a => 1}[:b].nil?
=> true

> nil.nil?
=> true

Nil and Ruby Interpreter

There’s an interesting feature concerning the nil object implementation, which many Ruby programmers don’t even know about. Take a look:

> nil.object_id
=> 4

Let’s run the Ruby interpreter again:

> nil.object_id
=> 4

Either it’s a coincidence or something (someone) stands behind it. As you may have guessed, I wouldn’t bother you if it wasn’t something more than just blind fate. In fact, it stems from the way that Matz designed the Ruby interpreter.

Why is the object id of nil equal to 4? First, you need to know that false and true variables work exactly the same way as nil does. They are singleton instances of FalseClass and TrueClass, respectively. When the Ruby interpreter boots up, it initializes FalseClass, TrueClass and NilClass. The result is:

> false.object_id
=> 0

> true.object_id
=> 2

> nil.object_id
=> 4

What happened to 1 and 3? Well, the first bit is reserved for Fixnum values (numbers) only. Simple and consistent.

So, know you not only know how to check if Ruby object is nil, but also you got to know some peculiar Ruby implementation details. I hope the article was worth reading.

comments powered by Disqus