True, False And Nil Objects In Ruby

TrueEvery 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

  • http://mattvanhorn.com Matt V

    “The id of the nil object is always 4 (don’t ask me why, I have no idea :))”

    look here: http://neeraj.name/blog/articles/662-why-the-id-of-nil-is-4-in-ruby

    • http://www.skorks.com Alan Skorkin

      Ahh, cheers for this, makes a lot more sense now. I love it when I learn interesting tidbits like that.

    • http://www.markthomas.org Mark Thomas

      Nice, but it doesn’t explain why Matz made it that way.

    • Michael Edgar

      That explanation doesn’t actually explain anything.

      Every object in Ruby is represented by a pointer, typedeffed as “VALUE” in C. Most objects, such as Arrays, Hashes, and so on, are a small struct of data in memory, which the VALUE points to. Fixnums, however, are constants and need no extra data – they’re just a number, which can be represented as a VALUE. Similarly, false is a constant, true is a constant, and nil is a constant. Their values, 0, 2, and 4, are based on bitmasks. This leaves the 1 bit unused. 1 is used for fixnums – to find the VALUE for a given integer, take 1 | (value << 1) — 10.object_id == 11, 4.object_id == 9, and so on. To test if a given VALUE is a fixnum constant in C, one only perform (val & 1).

      • http://www.skorks.com Alan Skorkin

        This makes it even clearer, thanks for sharing it with everyone.

  • Dave Wright

    “… Every expression in Ruby evaluates to an object and every object has a boolean value.”

    Objects dont have a boolean value, they can be used in a boolean context. The difference is slight but important. Consider the way C handles boolean expressions (remember, C has no boolean type): any non-zero value is considered a ‘true’ value. That does not make zero false or 127 true, it merely allows them to be evaluated in a particular setting – the actual values are not affected by this.

    As an example try comparing your objects to true…

    puts “w00t” if Object.new
    vs.
    puts ‘w00t’ if Object.new == true

    • http://www.skorks.com Alan Skorkin

      You’re right of course, the way I said it was somewhat awkward. The object returns whatever value it actually returns, i.e. strings return strings etc. But it can evaluate to a boolean when used in a boolean context.

  • http://www.timocracy.com Tim Connor

    Look at the values of true.object_id and false.object_id and you might see the pattern that explains why nil.object_id is 4. In the MRI, Matz packed objects ids so that the even numbers are for used for objects, with the first ones being taken by built-ins like true, false, nil, and the odds are for the integers (check out the object_ids of 0, 1, 2, etc).

    • http://www.skorks.com Alan Skorkin

      Thanks for the info, Matt V pointed out the same thing above, good to know.

  • Jude

    nice one to explain true, false

  • Robert Lowrey

    While it’s horribly wrong and I’ll probably be flamed to death for showing this, I’ve used something like this in a small script that was dealing with some data conversion issues and some date data was coming across as nil.

    The String method ‘makedate’ was the whole point but by adding ‘makdate’ to NilClass, you can do away with nil-checking (I had several dates to check & convert) and still get your desired result.

    I DO NOT recommend doing this as you probably should write the code to do the nil-checking, but I was tired of all the “unless yadi.nil?” I was adding to my little script.

    class NilClass
    def makedate
    Time.parse(“1980-01-01 00:00:00″)
    end
    end

    class String
    def makedate
    begin
    Time.parse(self)
    rescue ArgumentError
    Time.parse(“1980-01-01 00:00:00″)
    end
    end
    end

    • http://www.skorks.com Alan Skorkin

      I believe in not being too much of a purist. In some situations it makes sense to hack the hell out of something just to get it to work and save yourself some headache and annoyance :). If you need to you can go back to it and fix it up later.

  • Pingback: Разработка на Ruby и Rails c нуля » Эти загадочные True, False и Nil объекты Ruby

  • http://not-in-list.blogspot.com/ Nil

    You should not evaluate strings as boolean, because “warning: string literal in condition” and the result is always true, ant it is very likely that you do not wanted to express that. Test for emptiness!

    > print( (! “”.empty? ? “true” : “false”) + “\n” )
    false
    > print( (! “a”.empty? ? “true” : “false”) + “\n” )
    true

    • Peter

      This also leads to some inconsistency:

      >> nil.to_s ? true:false
      => true
      >> nil ? true:false
      => false

  • Pingback: Quora

  • Pingback: Ruby: Links, News and Resources (2) « Angel “Java” Lopez on Blog

  • Pingback: Ruby Notes - ToValhalla