Ruby: Is nil?

September 11, 2010 / category: Ruby / 19 comments

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.

My eBook: “Memoirs of a Software Team Leader”
Read more »

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) {
} 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!"

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 reffered 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.


There are 19 comments / Submit your comment

Milan Dobrota
September 11, 2010 06:17 PM

Should be:

unless my_object.nil?
  puts "There is no object!"

Lukasz Wrobel
September 11, 2010 08:57 PM

Of course there was a mistake... I've already fixed it, many thanks!

September 12, 2010 02:30 AM

Why didn't you use the "unless" version?

Lukasz Wrobel
September 12, 2010 11:12 AM

Just for the sake of readability; I think that "if my_object.nil?" is much more clearer in this case. I usually use the "unless" keyword in this way:

raise NotFound unless @post

October 21, 2011 06:48 AM

Really clear and thorough explanation, thanks.

So you're saying that I should always write: if x.object_id == 4 when I want to see if x is nil, then?

Just kidding.

December 29, 2011 02:32 AM

No, this does not work.

Calling: if my_object.nil?

If my_object is null results in an error.

Lukasz Wrobel
December 29, 2011 08:43 PM

No, this does not work.

Calling: if my_object.nil?

If my_object is null results in an error.

It does work, but only for objects being potentially nil. That is, a reference has to exist.

Calling nil? on an existing variable will always work, though calling this (or any other) method on an undefined variable causes the NameError to be raised.

To achieve what you wanted to achieve, you can call defined?:

> defined? my_object
=> nil

> my_object = 1
> defined? my_object
=> "local-variable"

> my_object = nil
> defined? my_object
=> "local-variable"
> my_object.nil?
=> true

March 12, 2012 08:30 PM


Learning Ruby right now, your article helped me out. Thanks!

May 05, 2012 04:33 PM

Well done, your articles are really clear and useful!

June 26, 2012 05:41 PM

This was really helpful. Thanks for taking the time to explain.

March 12, 2013 04:52 PM

Hey, great article. Thanks for mentioning how Fixnum ids are just the left-shift-plus-one of the value they represent. That's super cool. It raises an important question for a Ruby learner like myself: are Fixnums actual objects, or are they just pseudo-objects?

March 04, 2014 05:08 PM

This ruby n00b found this article helpful. Thank you.

February 04, 2015 04:05 PM

Very helpful - thanks!

June 03, 2015 12:28 PM

Very well explained. I am wondering if Ruby has got the similar way where null is handled with Optional in Scala and Java 8

June 20, 2015 11:55 PM

So.... 1.object_id = 3 and 2.object_id = 5 3.object_id = 7

Bring my shotgun im gonna shoot this logic.

January 22, 2016 02:18 AM

2016 and your article is still helping people...thanks!

July 18, 2016 03:47 AM

thanks for the insight !! these do help ~

July 26, 2016 01:31 PM

huhu Thanks Brother, helpful


August 03, 2016 02:07 PM

Good article. Thank You for explanation on nil value. Good to know it is an singleton.

You can use Markdown in your comments if you wish. Examples:

`inline code`
inline code
[My blog](
My blog
# use 4 spaces to indent
# a block of code
    def my_method(x)
      x = x + 1
def my_method(x)
  x = x + 1

* First.
* Second.
  • First.
  • Second.

> This is a citation.
> Even more citation.

I don't agree with you.

This is a citation. Even more citation.

I don't agree with you.

Submit your comment



(required, Markdown supported)


My eBook: “Memoirs of a Software Team Leader”

Read more »