Let's run some tests. First question: Can we set a variable to
> x = nil
So, yes. Can we test the variable?
> x == nil
And there we have it. They are the same.
We shouldn't stop there, though. Let's explore a little bit and see where the edge cases turn up.
(eval):142: undefined local variable or method 'y' for main:Object (NameError)
We cannot test a variable that does not exist. That makes sense. But what about a reference that doesn't exist?
> y = 
The array reference above demonstrates how we can use
.nil? to test if an element is defined or not.
A hash is also a reference.
> z = Hash.new
nil, really? It is a placeholder for undefined references. Things that don't exist raise errors. Things that don't exist in a declared data structure return
nil but don't raise an error. Study this concept for as long as it takes to really grasp it. Seriously.
> y = 6
=> [nil, nil, nil, nil, nil, 6]
In a hash, a key does not exist without an associated value. That is what defines a hash.
> z['z'] = nil
The complexity is slightly elevated from an array, but not by much. Instead of an ordered numerical index we have key names and unordered insertion of keys and respective values.
With a hash, we need a key name to query, hypothetical as it may be.
> z['some key').nil?