Булевы значения, nil и сравнения
Логика программы строится на ответах «да/нет». В Ruby за это отвечают true и false, а особняком стоит nil — «ничего», которое нужно уметь приручать.
Суть: в Ruby «ложными» считаются толькоfalseиnil; всё остальное (включая ноль и пустую строку) — «истина». Это правило определяет поведение всех условий.
Многие языки считают ноль или пустую строку «ложью». Ruby — нет. Здесь действует простое и строгое правило: ложны ровно два значения — false и nil. Число 0, пустая строка "", пустой массив [] — всё это в условии истинно. Запомнить это правило важнее, чем кажется: на нём спотыкаются программисты, пришедшие из JavaScript или Python.
puts "0 истинно" if 0 # напечатает — 0 это истина
puts "пусто истинно" if "" # напечатает — пустая строка истина
puts "nil ложно" unless nil # напечатает — nil ложь
puts "false ложно" unless false
Разбор: операторы сравнения
Сравнения возвращают true или false. Базовый набор знаком: == (равно), != (не равно), <, >, <=, >=. Особый оператор «космический корабль» <=> возвращает -1, 0 или 1 и используется для сортировки.
puts (3 <=> 5) # => -1 (меньше)
puts (5 <=> 5) # => 0 (равно)
puts (8 <=> 5) # => 1 (больше)
puts 5.between?(1, 10) # => true
Как работает под капотом: nil — это объект
В Ruby nil — не «пустота из ниоткуда», а единственный экземпляр класса NilClass. У него есть методы: nil.to_s даёт пустую строку, nil.to_a — пустой массив, nil.nil? — true. Это удобно, но и опасно: вызов несуществующего метода на nil — самая частая ошибка новичка, знаменитый NoMethodError: undefined method for nil.
любое выражение
|
ниже только эти два — ЛОЖЬ:
|
+-------+-------+
| |
false nil
| |
ВСЁ ОСТАЛЬНОЕ (0, "", [], "false") --> ИСТИНА
Та же идея «безопасного обращения к возможному nil» есть и в Python через проверку на None:
# Та же логика на Python ▶
user = None
# защищаемся от обращения к None
name = user.upper() if user is not None else "гость"
print(name) # гость
Частые ошибки
- Ждать, что 0 или "" — ложь. В Ruby они истинны. Если нужно проверить «пусто ли», используйте
.empty?или.zero?. - Вызывать методы на nil. Если переменная может быть
nil, защищайтесь оператором безопасной навигации&.—user&.nameвернётnil, а не упадёт. - Путать = и ==. Один знак — присваивание, два — сравнение. В условии это особенно коварно.
Best practices
- Используйте предикатные методы (с
?):arr.empty?,n.zero?,x.nil?— они выразительнее ручных сравнений. - Для значения по умолчанию применяйте
value || "по умолчанию"— еслиvalueложно (nil/false), возьмётся правое. - Защищайте цепочки вызовов оператором
&., когда звено может оказатьсяnil.
Глубже: операторы || и && как инструменты
Логические операторы в Ruby — не только про «истину и ложь», но и про выбор значений, и это меняет стиль кода. Оператор || возвращает первый «истинный» операнд, поэтому идиома name = input || "гость" читается как «возьми input, а если он nil или false — подставь гостя». Парный оператор && возвращает последний операнд, если все истинны, что удобно для безопасных цепочек: user && user.admin? не упадёт, даже если user равен nil. Есть и присваивающая форма ||=: запись @cache ||= compute означает «вычисли и запомни, только если ещё не вычислено» — классический приём ленивой инициализации и кэширования. Понимание того, что эти операторы возвращают не true/false, а сами значения операндов, открывает целый пласт лаконичных идиом. Главное — не переусердствовать: когда цепочка || и && разрастается, читаемость падает, и обычный if снова становится предпочтительнее.
Итог. Ложны только false и nil — всё остальное истинно. nil — это объект класса NilClass, и обращение к его методам как к обычному объекту приводит к NoMethodError. Спасает безопасная навигация &..