#---Nil---
nil
in Ruby represents “nothing” or “no value”.
It’s Ruby’s way of saying “this thing is empty” or
“this thing doesn’t exist”.
It’s similar to null
in other programming languages.
x = nil
p x # => nil
nil
is an object. It’s the only object of the class
NilClass
.
p x.class # => NilClass
It’s falsey in conditional statements (along with
false
).
if x
p "x is not nil"
else
p "x is nil"
end
## => "x is nil"
You can check for nil using either .nil?
or
comparing with nil.
p "x is NOT nil" if x
p "x IS nil" if x.nil? # => "x IS nil"
p "x is still nil" if x == nil # => "x is still nil"
nil
is not the same as any of these:
an empty string (""
), zero (0
), an empty array,
([]
) an empty hash ([]
), or an empty object.
(So be careful when you compare any object with nil
.)
p nil == '' # => false
p nil == 0 # => false
p nil == [] # => false
p nil == {} # => false
p nil == Object.new # => false
But nil
is nil
. So you can compare 2 variables
that are nil.
y = nil
p x == y # => true
When you try to access a hash key that doesn’t exist,
you get nil
.
h = {a: 'aa', b: 'bb'}
p h[:a] # => "aa"
p h[:c] # => nil
(If you want it to blow up with an exception saying
there’s no such key, you must use fetch
)
p h.fetch(:c)
## => 💥 blows up with:
## key not found: :c (KeyError)
When you access an array index that’s out of bounds,
you get nil
:
arr = [11, 22, 33]
p arr[2] # => 33
p arr[3] # => nil
p arr.fetch(3)
## => 💥 blows up with:
## index 3 outside of array bounds: -3...3 (IndexError)
In Go, there’s a concept called “zero-value”.
If you declare a variable and give it no initial value,
then a default value based on its type is assumed.
int
variable, it’ll be 0
string
, it is ""
(an empty string)bool
, it is false
. And so on.In Ruby, we can get something like that with
the nil.to_*
helper methods.
p nil.to_s # => ""
p nil.to_i # => 0
p nil.to_f # => 0.0
p nil.to_a # => []
p nil.to_h # => {}
p nil.to_json # => "null"
p nil.to_yaml # => "---\n"
Sometimes, nil
seeps into an array or a hash.
But you might not want it. You most likely only want the
non-nil items in the array/hash.
arr = [11, 22, nil, 33, 44, nil]
h = { a: 'aa', b: nil, c: 'cc' }
You can get them with compact
.
p arr.compact # => [11, 22, 33, 44]
p h.compact # => {a: "aa", c: "cc"}
Note that the original array and hash are unchanged.
.compact
only returns a new array/hash with nils
removed.
Use .compact!
to remove nils even from the original
variables.
arr.compact!
p arr # => [11, 22, 33, 44]
For an object to successfully respond to a method, it should first know about it.
name = 'john wick'
p name.upcase # => "JOHN WICK"
If you call a method that the object does not know about it, Ruby will scold you.
name = nil
p name.upcase
## => 💥 blows up with:
## undefined method 'upcase' for nil (NoMethodError)
And if that object is nil
,
you can avoid the exception by using the
safe navigation operator &.
It will return nil
instead.
p name&.upcase # => nil
Use this functionality with care. In the example above,
it is okay to use &.
only if it’s okay for name
to
be nil.