Nothingness and the truth

Now is a good time to talk about the concepts of nothingness and truth in Ruby.

Nil

We have briefly mentioned that in Ruby there is an object that represents “nothing”: the object nil.

That’s right. “Nothing” is a thing in Ruby (as well as in many other languages), albeit a very special one. We could ramble on the philosophical implications of this, but instead we’ll just look at how this is used in practice:

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

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

This will print out "eins". However, what happens if we try to receive the value for a key that has not been defined on the hash?

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

This will print out nil. Remember that every method call always will return some value? In cases where there’s nothing to return, it will return nil, which represents nothing :)

In Ruby, nil, nothing, is something else than, for example, 0, which represents something. An empty string "", an empty array [], or empty Hash {} also all represent something. So they’re not nil.

True and false

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

You have seen them 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.

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

The objects nil, true, and false also have classes, and you can check that in IRB yourself: nil.class, true.class and false.class.

For a reason that we don’t know Matz (the creator of Ruby) has decided to call these classes NilClass, TrueClass and FalseClass, instead of just Nil, True and False. If you ever meet him at a conference you can ask him :)

Truthiness and falsiness

Now, when we talked about if statements we used methods that actually return true and false values, like the odd? method on numbers does. Comparison operators like ==, < and > also return true and false, as in:

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

However, what happens when we use methods as conditions that do not return true or false, but something else, for example a string, number, or nil?

For example, consider the following:

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] will return nil because this key is not defined. Is nil equivalent to true or false? Or will this raise an error?

If you run the code above then you see that Ruby will execute the else branch. That means Ruby actually considers nil to be equivalent to not true, that is, false.

Now, lets use a key that actually is defined:

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

As you saw before dictionary[:one] will return "eins", because that’s the value associated with the key :one. Again, do you think "eins" is equivalent to true or false? Or will this raise an error instead?

If you run the code then you’ll see that Ruby now executes the if branch, and considers the condition (i.e. the string "eins") to be equivalent to true.

Think about this for second: Ruby considers everything to be equivalent to true that is not false or nil. Or put the other way around, Ruby only considers nil to be equivalent to false.

Because “is equivalent to true” or “is equivalent to false” is quite a clunky thing to repeat so often the programming community has come up with terms for this: truthiness and falsiness. So we can say that the string "eins" is truthy. And nil is the only other thing that is falsy in Ruby, except false itself.

To sum this up, if and unless look at the truthiness of a the value that is 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), instead they’re something, and therefore, in Ruby, truthy.

Here’s a pattern that you might see used when you look at other people’s code:

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

If you read this out loud, does it make sense to you?

The code first looks up the translation from the dictionary hash. And then it says If there’s a translation, then use it. Otherwise do something else.

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