У Руби есть универсальное представление о "правдивости" и "ложности".
В Ruby есть два специальных класса для булевых объектов: TrueClass
и FalseClass
, причем одноэлементные экземпляры обозначаются специальными переменными true
и false
соответственно.
Однако правдивость и ложность не ограничиваются экземплярами этих двух классов, концепция универсальна и применима к каждому объекту в Ruby. Каждый объект является либо правдивым, либо ложным. Правила очень просты. В частности, только два объекта являются ложными:
nil
, одиночный экземплярNilClass
иfalse
, одиночный экземплярFalseClass
Каждый другой объект правдив. Это включает даже объекты, которые считаются ложными в других языках программирования, таких как
Эти правила встроены в язык и не определяются пользователем. to_bool
не существует неявного преобразования или чего-либо подобного.
Вот цитата из спецификации языка Ruby ISO:
6.6 Булевы значения
Объект классифицируется как истинный объект или ложный объект.
Только false и nil являются ложными объектами. 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
также правдивы, но, согласно моим тестам, это не так:
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'
Это ошибка или желаемое поведение?