У Руби есть универсальное представление о « правдивости » и « ложности ».
Рубин делает два конкретных классов для объектов Boolean, TrueClass
и FalseClass
, с одноплодными случаями , обозначенных специальными переменными true
и false
, соответственно.
Однако правдивость и ложность не ограничиваются экземплярами этих двух классов, концепция универсальна и применима к каждому объекту в Ruby. Каждый объект является либо правдивым, либо ложным . Правила очень просты. В частности, только два объекта являются ложными :
nil
, единичный случайNilClass
иfalse
единичный случайFalseClass
Каждый другой объект является truthy . Это включает даже объекты, которые считаются ложными в других языках программирования, таких как
Эти правила встроены в язык и не определяются пользователем. Не существует to_bool
неявного преобразования или чего-либо подобного.
Вот цитата из спецификации языка Ruby ISO :
6.6 Булевы значения
Объект классифицируется как истинный объект или ложный объект .
Только ложь и ноль являются ложными объектами. false - единственный экземпляр класса
FalseClass
(см. 15.2.6), для которого оценивается ложное выражение (см. 11.5.4.8.3). nil - единственный экземпляр классаNilClass
(см. 15.2.4), для которого оценивается nil-выражение (см. 11.5.4.8.2).Объекты, отличные от false и nil , классифицируются как истинные объекты. Значение true является единственным экземпляром класса
TrueClass
(см. 15.2.5), для которого оценивается выражение true (см. 11.5.4.8.3).
Исполняемый Ruby / Spec, похоже, согласен :
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
Согласно этим двум источникам, я бы предположил, что Regexp
s также правдивы , но, согласно моим тестам, они не являются:
if // then 'Regexps are truthy' else 'Regexps are falsy' end
#=> 'Regexps are falsy'
Я проверял это на YARV 2.7.0-preview1 , TruffleRuby 19.2.0.1 и JRuby 9.2.8.0 . Все три реализации согласуются друг с другом и не соответствуют спецификации языка Ruby ISO и моей интерпретации Ruby / Spec.
Точнее говоря, Regexp
объекты, которые являются результатом вычисления Regexp
литералов, являются ложными , тогда как Regexp
объекты, которые являются результатом некоторых других выражений, являются правдивыми :
r = //
if r then 'Regexps are truthy' else 'Regexps are falsy' end
#=> 'Regexps are truthy'
Это ошибка или желаемое поведение?
!!//
ложно, но !!/r/
верно. Странно действительно.
!!/r/
производит false
для меня использование (RVM) Ruby 2.4.1.
//
в if // then
интерпретируется как тест (сокращение для if //=~nil then
) (это всегда ложно, независимо от шаблона), а не как экземпляр Regexp.
Regex.new("a")
это правда.