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.)
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."
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.”
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).
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...
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With