Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

if(!x) vs if(x==false) in ruby

Tags:

ruby

I don't understand the following code:

ruby-1.9.1-p378 > puts "nil is false" unless nil
nil is false
 => nil 
ruby-1.9.1-p378 > puts "nil isn't false" unless nil == false
nil isn't false
 => nil 

In most languages (of a C-base, at least), if(!cond) and if(cond==false) evaluate the same. What's going on here to make that not the case?

(I'd like the details of why, I understand that that is how it is.)

like image 266
Aaron Yodaiken Avatar asked Jun 21 '10 05:06

Aaron Yodaiken


People also ask

What evaluates to false in Ruby?

in a boolean context (if, &&, ||, etc.). Ruby has to decide whether these values count as true or false. If the value isn't literally "true" but evaluates as true, we call it "truthy." Likewise, if the value isn't literally "false" but evaluates as false, we call it "falsey."

Is true or false in Ruby?

Every object in Ruby has a boolean value, meaning it is considered either true or false in a boolean context. Those considered true in this context are “truthy” and those considered false are “falsey.” In Ruby, only false and nil are “falsey,” everything else is “truthy.”

How do you check if something is not nil in Ruby?

That's the easy part. In Ruby, you can check if an object is nil, just by calling the nil? on the object... even if the object is nil. That's quite logical if you think about it :) Side note : in Ruby, by convention, every method that ends with a question mark is designed to return a boolean (true or false).


2 Answers

Ruby considers that false and nil are the only two "falsy" values, while everything else is "truthy". This is by definition and can not be modified (at least in MRI). This definition is used for all builtin operators like if, unless, while, until, cond ? if_truthy : if_falsey, ||, &&, ...

Writing foo == bar will always call the == method on foo with bar as an argument. By default, nil, false, true and all other immediates like symbols, etc..., are only equal to themselves. This could be changed, though:

def nil.==(bar)
  super || bar == false
end
puts "nil == false" if nil == false  # => "nil == false"

In Ruby 1.9, you can also redefine the operator !, so unless foo is not necessarily the same as if !foo or the contrary of if foo:

def true.!
  true
end

puts "True?"   if  true # => "True?"
puts "or not?" if !true # => "or not?"

Not that anybody would recommend doing anything like this...

like image 182
Marc-André Lafortune Avatar answered Sep 28 '22 06:09

Marc-André Lafortune


nil is not equal to false by comparison over == because their semantic content is different (nil is no information, false is a boolean value). However, if you try to evaluate nil in a boolean context, it will be considered False, mostly for convenience' sake and idiomatic compatibility with other languages.

nil == a <=> nil != a <=> false is going to be the case for virtually any value of a except for nil.

So you can only tell that 'nil is not true' and 'nil is nil'. This is as far as ruby goes in its ways.

like image 41
Romain Avatar answered Sep 28 '22 08:09

Romain