A Healthy Respect of Null
I recently traveled from the over-populated World of Java into the beautifully rustic Land of (professional) Ruby. Like any traveler, I had a few companions (ideologies, habits and conventions) which kept me safe and sound in Java's harrowing landscape. But when I left Java for newer pastures some of those companions trailed along. One of them is named
Scary Null.
In Java -
null is not an object - just ask it:
null instanceof Object
will be false. Worse yet, attempting to use it for anything other than a place-holder and he'll throw his even scarier friend
NullPointerException at you. Over the years I learned a healthy respect for
null. He has one and only one job: to hold the place of something. How dare I use
null in a capacity for Which He Was Not Intended!
A Healthy Disrespect of Nil
In Ruby Land, however, he has a cousin:
nil. But
nil is not a fearful beast like
null. Nil is a charming little scamp, a first class object that does her best to help you out. This took some getting used to for me. I'm so used to writing code like this in Java:
int i = str == null ? 0 : Integer.parseInt(str);
that it almost feels awkward to do it the Ruby way:
i = str.to_i
In the back of my mind I think:
"Eric, what are you doing! What if 'str' is nil? I'll get an exception!" Au contraire. Since
nil is a real object, it doesn't throw exceptions -
nil is an object of the type
NilClass which implements plenty of useful methods, like:
- &
- |
- ^
- nil?
- to_a
- to_f
- to_i
- to_s
- to_yaml
Let's take the first three: &, | and ^. Since those are respectively "and", "or" and "xor", you can imagine what
nil represents: false. That makes code like this possible:
c is true. No exception. If I was smacked upside the head with a board and the ensuing brain damage caused me to
want nil to throw an exception in this situation, I could always override the method in
nilThe other methods are equally kind.
nil.to_s (to string) returns "" (empty string),
nil.to_a (to array) returns [] (empty array), and my favorite
nil.nil? return true - and is the only object that does.
Bring on the Fun
Nil is fun, but so what? If I attempt to use a method that doesn't exist, I'll still get an exception! True. However, since we know that
nil is a real object, and since Ruby can override object implementations on the fly (weee!) we can also add methods to
nil.
Consider the following code, that iterates until a string is constructed that is over 10 character long, then returns the string:
It outputs:
la
lala
lalala
lalalala
lalalalala
lalalalalala
Did you see something wrong with that picture? Not if you are from the World of Java. Initialize a variable, iterate, append and finally return the value on the correct conditions. But:

Why declare a variable that we only use inside the loop and return? Why indeed. Let's try it again without declaring the variable.
We get an error :(.
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.+
Oh - it looks like Ruby requires us to define variables first. And since
str += "la" is the same as
str = nil + "la" when
str is not yet defined, it makes sense that it complains.
But wait! Re-read the last sentence. Of course! Ruby thinks that
str is
nil, and is attempting to append the string "la" to it. So what would happen if the
nil.+ method was declared? What if it just returned whatever was passed to it?
def nil.+(o)
o
end
Now we're cooking with gas! Try and run the above code now. It works(!) since our
nil.+ method just set
str to "la". For each successive loop, str just uses the standard string append method instead.
There are a few methods I like to add to
nil. Just create a file named "safe_nil.rb" in your library, and add it like any requires.
Now you can safely do things like this:
instead of