Every expression and every object in Ruby has a boolean value, which means that every object and every expression must either evaluate to true or to false. This makes true and false rather special values. But, they are not just empty value or simple keywords, just like with everything else, both true and false are Ruby objects.
The True And False Objects
You’re probably aware that true and false are reserved words in Ruby which means you can’t use them as a variable or method name. But both true and false are also fully fledged objects. Ruby has two special classes called:
TrueClass
and
FalseClass
and the objects true and false are the only instances of these classes. Infact Ruby won’t let you create any more instances of these classes, you can go ahead and try e.g.:
irb(main):001:0> true.class
=> TrueClass
irb(main):002:0> false.class
=> FalseClass
irb(main):003:0> p = TrueClass.new
NoMethodError: undefined method `new' for TrueClass:Class
from (irb):3
irb(main):004:0> q = FalseClass.new
NoMethodError: undefined method `new' for FalseClass:Class
from (irb):4
irb(main):005:0>
But what about every Ruby expression evaluating to either true or false? Well, every Ruby expression evaluates to an object and every Ruby object in turn can be used in a conditional statement which means every object ultimately must evaluate to a boolean value. You can test this out on your own:
irb(main):001:0> if :hello
irb(main):002:1> puts 'the boolean value of a string or symbol object is true'
irb(main):003:1> end
the boolean value of a string or symbol object is true
irb(main):004:0>
irb(main):005:0* if 5
irb(main):006:1> puts 'the boolean value of an integer object is true'
irb(main):007:1> end
the boolean value of an integer object is true
irb(main):008:0>
irb(main):009:0* if !false
irb(main):010:1> puts 'the boolean value of false would have been false'
irb(main):011:1> end
the boolean value of false would have been false
irb(main):012:0>
irb(main):013:0* if nil
irb(main):014:1> puts 'nil can\'t be true'
irb(main):015:1> else
irb(main):016:1* puts 'the boolean value of nil is false'
irb(main):017:1> end
the boolean value of nil is false
irb(main):018:0>
irb(main):019:0* if def method; end
irb(main):020:1> puts 'can\'t end up here'
irb(main):021:1> else
irb(main):022:1* puts 'a method definition evaluates to false'
irb(main):023:1> end
a method definition evaluates to false
irb(main):024:0>
You can keep trying this with any Ruby expression or object and you will always be able to use it in an if statement. You can also prove that the true and false values you get are always the same object (i.e. the same instance of TrueClass or FalseClass), just ask the objects for their id, you will find that the id will always be the same. More than that the object id of false is always 0 and the object id of true will always be 2:
irb(main):001:0> true.object_id
=> 2
irb(main):002:0> false.object_id
=> 0
irb(main):003:0>
So, the lessons we learn from this are as follows. Every expression in Ruby evaluates to an object and every object has a boolean value. The boolean values are always the same instance of the TrueClass and FalseClass classes and will therefore always have the same id. Most objects in Ruby will have a boolean value of true. Only two objects have a boolean value of false, these are the false object itself and the nil object.
The Nil Object
The nil object is another special one in Ruby. That’s right, this one is also an object and not just a keyword. You can probably guess this after the previous section, but the nil object is the only instance of a special Ruby class – the NilClass. I’ve already mentioned that nil is one of the two objects (many expressions can have a false value, but the only two object to have a boolean value of false are nil and false) that have a boolean value of false in Ruby.
Just like with true and false, every nil you use in your Ruby application will be the same instance as you will find out if you query it’s id. The id of the nil object is always 4 (don’t ask me why, I have no idea :)):
irb(main):001:0> nil.class
=> NilClass
irb(main):002:0> nil.object_id
=> 4
irb(main):003:0>
The really interesting thing about the nil object in Ruby is the fact that it can act like a bit of a Null Object (as in the pattern) out of the box. The nil object already comes equipped with some methods for you to use so that you don’t get pesky inconvenient errors if you accidentally end up with a nil object as a result of executing some code. For example, you can try and convert your nil object to a string or to an integer and it will give sensible values:
irb(main):002:0> nil.to_s
=> ""
irb(main):003:0> nil.to_i
=> 0
irb(main):004:0>
But due to the fact that you can always add methods to object instances in Ruby and the nil object is always the same instance, you can decorate your nil object with any interesting method that your code may need, to be able to treat nil like a Null Object, e.g.:
irb(main):001:0> def nil.quack
irb(main):002:1> puts 'Quack, quack, quack, can\'t make pate out of me, I am nil'
irb(main):003:1> end
irb(main):004:0> nil.quack
Quack, quack, quack, can't make pate out of me, I am nil
irb(main):005:0>
Now if your code is playing with objects that quack like a duck and you end up with a nil instead of a DuckLike object, your nil object will be able to quack a sensible default value (or raise an error if you prefer).
I think this is pretty powerful stuff. A basic pattern built right into the language, you just need to take advantage of it. Speaking of converting things to string or integers, I’ve been meaning to have a look at the various conversion method in Ruby which I will most likely do very soon. As well as that I’d like to take a glance at object comparison, some interesting things you can do with strings and then dig into collections and enumerables, so stay tuned, we’re going to be getting our Ruby expertise on (if rappers can turn phrase like that then so can I :)).
Image by pittaya