Ruby has a universal idea of "truthiness" and "falsiness".
Ruby does have two specific classes for Boolean objects, TrueClass
and FalseClass
, with singleton instances denoted by the special variables true
and false
, respectively.
However, truthiness and falsiness are not limited to instances of those two classes, the concept is universal and applies to every single object in Ruby. Every object is either truthy or falsy. The rules are very simple. In particular, only two objects are falsy:
nil
, the singleton instance ofNilClass
andfalse
, the singleton instance ofFalseClass
Every single other object is truthy. This includes even objects that are considered falsy in other programming languages, such as
These rules are built into the language and are not user-definable. There is no to_bool
implicit conversion or anything similar.
Here is a quote from the ISO Ruby Language Specification:
6.6 Boolean values
An object is classified into either a trueish object or a falseish object.
Only false and nil are falseish objects. false is the only instance of the class
FalseClass
(see 15.2.6), to which a false-expression evaluates (see 11.5.4.8.3). nil is the only instance of the classNilClass
(see 15.2.4), to which a nil-expression evaluates (see 11.5.4.8.2).Objects other than false and nil are classified into trueish objects. true is the only instance of the class
TrueClass
(see 15.2.5), to which a true-expression evaluates (see 11.5.4.8.3).
The executable Ruby/Spec seems to agree:
it "considers a non-nil and non-boolean object in expression result as true" do if mock('x') 123 else 456 end.should == 123 end
According to those two sources, I would assume that Regexp
s are also truthy, but according to my tests, they aren't:
if // then 'Regexps are truthy' else 'Regexps are falsy' end
#=> 'Regexps are falsy'
I tested this on YARV 2.7.0-preview1, TruffleRuby 19.2.0.1, and JRuby 9.2.8.0. All three implementations agree with each other and disagree with the ISO Ruby Language Specification and my interpretation of the Ruby/Spec.
More precisely, Regexp
objects that are the result of evaluating Regexp
literals are falsy, whereas Regexp
objects that are the result of some other expression are truthy:
r = //
if r then 'Regexps are truthy' else 'Regexps are falsy' end
#=> 'Regexps are truthy'
Is this a bug, or desired behavior?
Regex.new("a")
is truthy. – Streetman!!//
is false but!!/r/
is true. Strange indeed. – Insessorial!!/r/
producesfalse
for me using (RVM) Ruby 2.4.1. – Goldshlag//
inif // then
is interpreted as a test (a shortcut forif //=~nil then
) (that is always falsy whatever the pattern) and not as an Regexp instance. – Whetif //
will act upon$_
as is the case for cli usage.. for example:seq 10 15 | ruby -ne 'print if /[35]/'
is same asseq 10 15 | ruby -ne 'print if $_ =~ /[35]/'
– Tuckerbagruby -le 'print "foo" if //'
doesn't print anything, whereasruby -le '$_ = ""; print "foo" if //'
will printfoo
... so, I think it depends upon what is the default value of$_
– Tuckerbag!!/r/ #=> false
, but the prefixed!
s are actually syntactic sugar forBasicObject#!
, so written as/r/.!.!
,true
is returned regardless as to what$_
is set to and as one would expect for Ruby. – Halverson