Home > Blockchain >  Why does an empty String returns false when comparing to boolean in ruby?
Why does an empty String returns false when comparing to boolean in ruby?

Time:07-15

It might be a dumb question, but can someone please explain this:

if ""
  true
else
  false
end
=> true (OK)
!!("")
=> true (OK)
"" === true
=> false (OK)
"" == true
=> false (But why?)

Have a nice day!

CodePudding user response:

The basic concept of this question is a deep misunderstanding of Ruby operators. Here's the short of it - there's no such thing as operators in Ruby! All this !, =, == and === that you throw around - these are not operators.

So what's going on?

Ruby is an object oriented language (a real one, not like that fake Java and JavaScript things) and all these fancy character sequences you think of as operators are actually method calls on the object in their left:

  • == method usually checks for equality - is the object on the right equal in content.
  • === method is not used for "strict equality" or "identity" like it is often in other languages - some Ruby objects that implement it use it for "membership" tests, like in ranges ((1..3) === 2 ==> true) or regular expressions (/el/ === "hello" ==> true you can think of regular expressions as the group of all strings that would match), others implement it as equals.

So - how is the if working? Well, if and other "forced boolean contexts" check for "falsehood". In Ruby we recognize two false values - false and nil, everything else will run the truth branch of an if. This is actually the method ! that you also used in your second example. This method is implemented in BasicObject to return true for all objects, except if the object's type is the type of false - FalseClass or the type for nil - NilClass, in which case it returns true.

So your examples actually mean:

  1. Check for the truthiness of "". Because that value's type is neither FalseClass or NilClass, it is always true.
  2. For the value "", call the method ! - which will return false because the object is neither a FalseClass or a NilClass - then call ! on the result, which will return true because false is a FalseClass instance.
  3. For the value "" call the method === with the value true, but since it is an alias for == - call that instead (see 4).
  4. For the value "" call the method == with the value true. String's implementation of == will never return true for an argument that isn't a String type.

CodePudding user response:

The only falsy values in Ruby are false and nil. Everything else is "truthy," but not necessarily equal to true. This includes empty objects like a String, Hash, or Array.

Pragmatically, it might help to think of == as "comparably equivalent to" rather than "equals." For example:

1 == 1.0 #=> true

This is true even though one is an Integer and one is a Float because they are comparably equivalent in value, even if they aren't the same object or of the same type.

In the same way, "" is truthy because it is not comparably equivalent to false or nil. However, it's also not the same object type as true, nor comparably equivalent to true. An empty String is simply "not falsy," which makes it truthy but not actually true.

Remember, only false and nil are falsy. Everything else, and I mean everything, is truthy even if it isn't strictly speaking true.

CodePudding user response:

In Ruby, the only "falsey types" are FalseClass and NilClass, which have the instances false and nil respectively. All other values are considered "truthy". This is possibly different to what you'd expect coming from other C-like values, in which we do things like this pretty freely:

int x = get_value();
if (x) { /* implied x != 0 }

So, if you had something like this in Ruby:

puts 0 if 0     # => "0"
puts 1 if ""    # => "1"
puts 2 if []    # => "2"
puts 3 if false # => nil
puts 4 if true  # => "4"
puts 5 if nil   # => "5"

So, if "" acts truthy, why isn't it equal to true? If that were how we defined ==, then this would also need to resolve to true then, since both values are truthy:

"1" == "2"

The difference here is that == is asking if two things are the same, which "" and true are most certainly not. Further, Ruby does not automatically convert types for you (like other languages like JavaScript do), so "" does not automatically get converted to a boolean during its comparison.

  •  Tags:  
  • ruby
  • Related