Nothingness and the Truth

Learn about truthiness, falsiness, and nothingness.

Now is a good time to explore the concepts of nothingness and truth in Ruby. First, let’s also do a quick recap to build some context.

The nil object

We’ve briefly mentioned that in Ruby, there’s an object that represents nothing, nil.

Remember how we can receive a value associated with a key from a hash?

Press + to interact
dictionary = { :one => "eins", :two => "zwei", :three => "drei" }
p dictionary[:one]

This prints out "eins". However, what happens if we try to receive the value for a key that hasn’t been defined on the hash?

Press + to interact
dictionary = { :one => "eins", :two => "zwei", :three => "drei" }
p dictionary[:four]

This prints out nil. Remember that every method call always returns some value. In cases where there’s nothing to return, it returns nil, which represents nothing.

Note that nil isn’t 0, which represents something. An empty string (""), an empty array ([]), or an empty hash ({}) also all represent something. So, they’re not nil.

The true and false objects

We’ve also discussed that in order to represent truth and the opposite of it, Ruby also knows the values true and false.

We’ve seen them as returned values when we tried some of the methods on numbers, strings, and arrays, like 3.odd?, "a string".start_with?("a"), or [1, 2, 3].include?(2).

These so-called predicate methods always return either true or false.

Remember: Predicate methods end with a question mark and return true or false.

They have classes

The nil, true, and false objects also have classes, and we can verify that: nil.class, true.class and false.class.

Truthiness and falsiness

When we discussed if statements, we used methods that actually return true and false values, like the odd? method on numbers do. Comparison operators like ==, <, and > also return true and false, as in:

Press + to interact
number = 3
if number >= 5
puts "The number #{number} is greater than 5, or equal to 5"
else
puts "The number #{number} is less than 5"
end

What happens when we use methods as conditions that don’t return true or false, but something else, like a string, number, or nil, for example?

Consider the following:

Press + to interact
dictionary = { :one => "eins", :two => "zwei", :three => "drei" }
key = :four
if dictionary[key]
puts "The dictionary defines a value for the key #{key}."
else
puts "The dictionary does not define a value for the key #{key}."
end

As we saw before, dictionary[:four] returns nil because this key isn’t defined. Is nil equivalent to true or false? Or will this raise an error?

If we run the code above, then we should see that Ruby executes the else branch. That means Ruby considers nil equivalent to not true, that is, false.

Now, let’s use a key that’s actually defined and think about the output we expect to see:

Press + to interact
dictionary = { :one => "eins", :two => "zwei", :three => "drei" }
key = :one
if dictionary[key]
puts "The dictionary defines a value for the key #{key}."
else
puts "The dictionary does not define a value for the key #{key}."
end

Of course, dictionary[:one] returns "eins", but is "eins" equivalent to true or false? Or will this raise an error instead?

Running the code shows that Ruby now executes the if branch and considers the condition (the "eins" string) to be equivalent to true.

Remember: Ruby considers everything equivalent to true that isn’t false or nil. Ruby only considers nil to be equivalent to false.

Because repeating these true or false equivalencies can become quite cumbersome, the programming community has come up with one-word terms for this: truthiness and falsiness. So, we can say that the "eins" string is truthy and that nil is the only other thing that’s falsy in Ruby, except false itself.

To sum this up, if and unless look at the truthiness of the value returned by the condition. Everything except false and nil is truthy, including strings, numbers, arrays, hashes, and every other object.

This also includes the number 0, empty strings (""), arrays ([]), and hashes ({}). These aren’t nothing (nil), so they’re truthy.

Here’s a common pattern:

Press + to interact
dictionary = { :one => "eins", :two => "zwei", :three => "drei" }
key = :one
translation = dictionary[key]
if translation
puts "The translation for #{key} is: #{translation}."
else
puts "The dictionary does not define a translation for the key #{key}."
end

The code first looks up the translation from the dictionary hash. It then uses the translation if it’s present or does something else.

Ruby’s concept of truthiness allows us to write our code in this concise way that almost reads like English. That’s another reason why many people love Ruby so much.