This is a read-only archive!

NilClass

Here's a reason to love Ruby. In Ruby, nil is the value an unintialized variable gets. Similar to undef in Perl. In Ruby though, everything is an object. nil is an object too, of class NilClass. This lets us do strange and wonderful things, for example when referencing multi-dimensional arrays.

Now, suppose you have a hash and you want to test for the existence of a key in the hash. You can use something like this:

hash = {'test' => 1}
puts hash['blarg']

Output:

nil

Since nil counts as false in boolean tests, you can do

hash = {'test' => 1}

if hash['blarg'] then
    puts "EXISTS!"
else
    puts "NIL!"
end

Output:

NIL!

Same idea for arrays.

Now suppose, you have an array of arrays or a hash of hashes. Let's try the same thing.

aoa = Array.new
aoa[0] = Array.new
aoa[0][1] = 'Yoink'

puts aoa[0][1]
puts aoa[0][2]
puts aoa[1][0]

Output:

Yoink
nil
test.rb:8: undefined method `[]' for nil:NilClass (NoMethodError)

Well, how unpleasant. Our script dies a horrible death. That's because aoa[1] returns nil, and nil has no method called [].

One solution is to check to make sure the first-level array is initialized.

aoa = Array.new
aoa[0] = Array.new
aoa[0][1] = 'Yoink'

if aoa[1] then
    if aoa[1][0] then
        puts aoa[1][0]
    else
        puts "nil second-level array!"
    end
else
    puts "nil first-level array!"
end

Output:

nil first-level array!

However a spiffier and lazier solution is just to give NilClass a method called []. This is possible because Ruby lets you modify class definitions for any class. Let's try the first example that died when we ran it:

class NilClass
    def [] (*args)
        return nil
    end
end

aoa = Array.new
aoa[0] = Array.new
aoa[0][1] = 'Yoink'

puts aoa[0][1]
puts aoa[0][2]
puts aoa[1][0]
puts aoa[1][0][123][456]['blarg?']

Output:

Yoink
nil
nil
nil

Now at least we don't die. You don't have to return false of course. You can do any kind of screwy thing you want.

There are obviously times when you WANT this kind of thing to die. In fact, probably most of the time you should let this die, so you aren't sending nils around pretending to be data. Silent bugs are usually the worst kind of bugs. But there are times when this kind of thing will come in handy.

June 05, 2006 @ 4:18 AM PDT
Cateogory: Programming
Tags: Ruby, nil