У Руби есть универсальное представление о « правдивости » и « ложности ».
Рубин делает два конкретных классов для объектов 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
Согласно этим двум источникам, я бы предположил, что Regexps также правдивы , но, согласно моим тестам, они не являются:
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")это правда.