Photo by Sharon Moy on Unsplash

The nil value in Ruby

Tech - RubyCademy
RubyCademy
Published in
3 min readJul 18, 2018

--

In this article we’re going to explore the following topics:

  • the nil value
  • the NilClass class
  • the nil? method implementation

The nil value

The nil value is used to express the notion of a “lack of an object”.

It’s also used by the Garbage Collector — which implements a mark-and-sweep algorithm — to decide if an object should be destroyed or not.

Unlike other languages, the nil value isn’t used to express emptiness, false, or zero.

As everything in Ruby is an object, the nil value refers to the non-instantiable NilClass class.

The NilClass class

NilClass is a built-in class provided by Ruby. This class is not instantiable.

irb> NilClass.new
NoMethodError (undefined method `new' for NilClass:Class)

When a message is sent to nil, a hard-coded C-level “class” called rb_cNilClass — which corresponds to the NilClass in Ruby — is used as the receiver of the message.

Then the message will be found and sent among the instance methods of the new receiver.

So, nil acts more like a keyword than an instance. As it is just a way to express the “lack of an object” notion.

On the other hand, the NilClass encapsulates all the logic and is used when the receiver of a message is nil.

Feel free to have a look to my answer on StackOverflow for further information

The nil? method

Calling nil? helps you to determine if the receiver is an object or not

irb> "I'm an object".nil?
=> false
irb> a = nil
=> nil
irb> a.nil?
=> true

Pretty simple. isn’t it?

Let’s have a look at how this method is implemented in the Ruby source code.

Ruby is written in C. But, don’t panic, this is not a problem if you are unfamiliar with this programming language because the code that we’ll see is pretty simple

// in ruby/object.c
void InitVM_Object(void) {
...
rb_define_method(rb_mKernel, "nil?", rb_false, 0);
...
rb_define_method(rb_cNilClass, "nil?", rb_true, 0);
...
}

The function InitVM_Object(void) is called during the Ruby VM setup. This function is in charge of setting up all the environments and classes related to the Object class.

the rb_define_method(klass, message, function, argc) is used to add a message to a module/class and to link this message to a C-level function.

So, the rb_define_method(rb_mKernel, “nil?”, rb_false, 0); adds the "nil?" message to the Kernel module and links this message to the rb_false function. the last argument is the number of arguments that take the method — here no argument is expected.

As the Kernel module is included in the Object class and the Object class is the default parent class of any class in Ruby, then almost all the classes can handle the nil? method.

Feel free to read the Ruby Object Model article if you are unfamiliar with the Kernel module.

So, let’s see how the rb_false function is implemented

static VALUE
rb_false(VALUE obj)
{
return Qfalse;
}

The rb_false function returns Qfalse — which is the C-level value for Ruby false.

This means that, by default, all the objects are not nil.

Now let’s have a look at the implementation of NilClass#nil? via the rb_true function

static VALUE
rb_true(VALUE obj)
{
return Qtrue;
}

The rb_true function returns Qtrue — which is the C-level value for Ruby true.

This means that the NilClass#nil? method overrides the Kernel#nil? method (which returns false) to make it return true.

This is a clever implementation that respects the OOP principle by using inheritance to specialize the NilClass class.

Ruby Mastery

We’re currently finalizing our first online course: Ruby Mastery.

Join the list for an exclusive release alert! 🔔

🔗 Ruby Mastery by RubyCademy

Also, you can follow us on x.com as we’re very active on this platform. Indeed, we post elaborate code examples every day.

💚

--

--