Nothingness and the Truth
Learn about truthiness, falsiness, and nothingness.
We'll cover the following
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?
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?
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
orfalse
.
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:
number = 3if number >= 5puts "The number #{number} is greater than 5, or equal to 5"elseputs "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:
dictionary = { :one => "eins", :two => "zwei", :three => "drei" }key = :fourif dictionary[key]puts "The dictionary defines a value for the key #{key}."elseputs "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:
dictionary = { :one => "eins", :two => "zwei", :three => "drei" }key = :oneif dictionary[key]puts "The dictionary defines a value for the key #{key}."elseputs "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’tfalse
ornil
. Ruby only considersnil
to be equivalent tofalse
.
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:
dictionary = { :one => "eins", :two => "zwei", :three => "drei" }key = :onetranslation = dictionary[key]if translationputs "The translation for #{key} is: #{translation}."elseputs "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.