nil, nil?, true and false in Ruby
A friend of mine I'm teaching Ruby to asked me just a few days ago about the difference between nil and false and nil and nil? in Ruby. I gave him a very short answer:
nil = null
false = boolean value
nil? is a method
yes, I kinda lied to him about the null and false, but here is the long answer:
First of all, in order to understand how nil, true and false works you have to know that in Ruby:
- Every expression evaluates to false or true
- Every object evaluates to false or true.
conclusions:
- Expressions and objects never evaluates to nil
- nil and false are different each other
so, we all know that true and false are boolean values but what is nil and nil? anyway?
nil represents the nothing, null, None; some books say that it's the emptiness, I don't like to use that term because it sounds to me like it represents an empty string or an empty object and that isn't the case at all.
nil? is a method, more precisely, it's an instance method of the Object class, it's like asking "is my_object nil?":
NOTE: "expression/object # => value" means that such "expression" or "object" returns such "value".
my_object = nil foo = "baz" my_object.nil? # => true foo.nil? # => false
Second, there's a big difference between the object's value and the value an object evaluates to:
- The value of
nilis nil - The value of
falseis false - The value of
trueis true
nilevaluates to falsefalseevaluates to falsetrueand everything, everything, everything else evaluates to true
Let's see some examples:
bar = "silence is foo"
- The value of
baris "silence is foo" barevaluates to true
foo = ""
- The value of
foois an empty string fooevaluates to true
baz = 0
- The value of
bazis zero bazevaluates to true
qux = nil
- The value of
quxis nil quxevaluates to false
corge = false
- The value of
corgeis false corgeevaluates to false
That's why we don't need to do things like:
my_object = nil if !my_object.nil? puts "my_object is not nil" end if my_object == nil ... end if my_object != nil puts "my_object is not nil" end
Since we know nil evaluates to false, we'd do instead:
if my_object #it won't hit this part end unless my_object #it'll hit this part end
you should be aware that if you need to know if an object is exactly nil the code above won't help you in some cases. Look:
my_object = false
unless my_object
puts "my_object evaluates to false but we don't know if it's nil OR false"
end
unless my_object.nil?
puts "we certainly know that my_object is not nil"
end
my_object = nil
if my_object.nil?
puts "we certainly know that my_object is nil, anything else"
end
Let's see another case now with hashes, don't do this:
my_hash = {:name => "Ruby" }
my_hash[:version] # => nil (if a key doesn't exist in a hash it will return nil)
if !my_hash[:version].nil?
puts "The version is #{my_hash[:version]}"
end
if my_hash[:version] != nil
puts "The version is #{my_hash[:version]}"
end
if my_hash[:version] == nil
...
end
Instead we should do:
if my_hash
puts "even an empty hash will evaluate to true"
end
if my_hash.nil?
puts "you won't see this"
end
unless my_hash
puts "you won't see this"
end
unless my_hash.nil?
puts "we certainly know that my_hash is not nil and it is not false."
end
if my_hash[:version]
puts "you won't see this
else
puts "hash[:version] doesn't exist"
end
unless my_hash[:version]
puts ":version key doesn't exists"
end
if my_hash[:name]
puts "we know my_hash has a :name key"
end
Cool! now I have to say a last thing.
In Ruby, the value every object evaluates to is not a native boolean value it's actually an object.
meaning, nil, false and true are not simple keywords but objects and every object is instance of a class, in this case:
nilis instance of NilClassfalseis instance of FalseClasstrueis instance of TrueClass
A real world example of why is this very useful? What about the Whiny Nils in Ruby on Rails?.
oh, yeah, but why nil and false, why don't just false?
false and true are used in boolean expressions and nil is the value a method returns when something went wrong or when there's nothing to return, pretty different than false, don't you think?
Let's see some examples:
puts "foo" # => nil
The Kernel#puts method prints the given string in the STDOUT and returns nil, why we would want Kernel#puts to return false after all? Of course, there's a lot of methods that returns nil in the same fashion, like Regexp#match.
"foo" == "foo" # => true "foo" == "bar" # => false nil.nil? # => true
That's all folks, please, don't be shy, leave a comment.
Thanks for reading!
August 16th, 2010 - 09:48
You’re claims of “it is not false” are incorrect.
false.nil? returns false so your statements using unless my_object.nil? are incorrect.
unless false.nil?
puts “we certainly know that false is not nil and it is not false.” #this is incorrect, false is false and the puts executes
end
August 16th, 2010 - 11:14
Hey Corey, you’re totally right. Actually, I just realized that even fixing that error it wouldn’t say what I wanted to say, which is basically:
If you do want to know if an object is nil, use
nil?.if you do only want to know if it evaluates to false (it’s false or nil), use
if my_objectorunless my_objectso I made the necessary changes. It’d be nice if you let me know what you think.
Thanks!
August 15th, 2010 - 09:11
Also check out the present? and blank? methods to check for empty arrays, empty hashes, zero length strings, etc:
http://api.rubyonrails.org/classes/Object.html#M000011
August 15th, 2010 - 11:12
the main reason why I didn’t include those methods is because they are rails extensions to the Object class, they aren’t Ruby methods, so I wanted to keep the post ruby-specific, but I’m making a post about those methods then I’ll take your recommendations into account, thanks a lot!!!!
August 14th, 2010 - 14:26
Thank you for the lesson
August 13th, 2010 - 02:25
Pretty good explanation, thanks a lot my friend.
August 13th, 2010 - 02:29
My pleasure, my friend! ^_^ thanks for reading.
August 13th, 2010 - 02:13
It was a flighty lecture and pretty explanatory. Congratulations
August 12th, 2010 - 16:16
Thanks for clearing up this
August 12th, 2010 - 17:27
thanks for reading!