У Crystal є тип Nil, який може мати лише одне значення: nil.
Його використовують, щоб позначити відсутність значення; він подібний до null або None в інших мовах.
Значення nil можуть повертати різні методи, наприклад String#[]?, який повертає nil, якщо індекс виходить за межі.
"foo"[10]? # => nil
Crystal має так звані NULL REFERENCE CHECKS, а це означає, що всі типи не можуть набувати значення nil, якщо не вказати цього явно.
Тобто не можна присвоїти nil змінній, якщо явно не оголосити її як тип Nil.
Своєю чергою, це означає, що компілятор автоматично перевірятиме нульові посилання.
Існують різні підходи до роботи зі значеннями nil.
nil, як і false, є неправдивим значенням.
Це означає, що в умовних конструкціях та інших місцях, де потрібне неправдиве або правдиве значення, він поводитиметься так само, як false.
if nil
puts "nil is truthy"
else
puts "nil is falsey"
end
# => nil is falsey
Це означає, що правдива гілка не виконається, якщо змінна, яка може містити nil, має значення nil.
foo = "boo"[2]? # It is possible that foo is nil
if foo
p foo.class # => Char
end
У Crystal є метод, який дає змогу перевірити, чи значення дорівнює nil.
Він називається nil? і доступний для всіх обʼєктів.
foo = "boo"[2]?
if foo.nil?
puts "foo is nil"
else
puts "foo is not nil"
end
Ситуація трохи інша, якщо просто використати значення в умовній конструкції, адже в попередніх прикладах і false, і nil вважалися б неправдою.
Тут неправдивим вважається лише nil, бо якби це був false, то він не був би nil, а отже, був би правдивим.
Найпростіший спосіб мати справу зі значеннями nil - подбати про те, щоб вони взагалі ніколи не ставали nil.
Оператор or (||, логічне або) часто використовують, коли мають справу з Bools, але якщо правильно його зрозуміти, його можна застосовувати й для роботи зі значеннями nil.
Оператор or перевіряє, чи перше значення є правдивим; якщо ні, використовується друге значення.
Це дає змогу зробити так, що якщо значення дорівнює nil, воно буде неправдивим, і тому використається друге значення.
"foo"[10]? || "bar" # => "bar"
Ваша Величність влаштовує званий обід у столиці Кальмарської унії, Копенгагені. Це найбільше свято року, і всю знать запрошено. Але країною ширяться чутки про змову, щоб отруїти Вашу Величність.
Її Величність попросила нас, королівського шукача отрути, зʼясувати, чи не отруєна якась страва чи напій. Її Величність планує подати з їжі лише Mushroom pasties, а от напої будуть найрізноманітніші.
Якщо страва не та, яку замовила Її Величність, є велика ймовірність, що її отруєно. А якщо страва не та, яку замовила Її Величність, її слід викинути.
Реалізуйте метод check_food?, який приймає аргумент food, що містить назву страви як String.
Метод має повернути страву, якщо це Mushroom pasties; інакше він має повернути nil.
CastleDinner.check_food?("Mushroom pasties")
# => "Mushroom pasties"
CastleDinner.check_food?("Bread")
# => nil
Можливо, напій отруєний, але визначити це трохи складніше.
Напій отруєний, якщо в його назві немає літери i; регістр не має значення.
Отруєний напій слід викинути.
Реалізуйте метод check_drink?, який приймає аргумент drink, що містить назву напою як String.
Метод має повернути напій, якщо він не отруєний; інакше він має повернути nil.
CastleDinner.check_drink?("Apple juice")
# => "Apple juice"
CastleDinner.check_drink?("Tea")
# => nil
Ваша Величність не хотіла б, щоб гості непокоїлися через можливу отруту в їжі. Тож якщо напій отруєний, його слід замінити новим, а саме Apple juice.
Реалізуйте метод replace_drink, який приймає аргумент drink, що містить назву напою як String.
Метод має повернути напій, якщо він не отруєний; інакше він має повернути "Apple juice".
CastleDinner.replace_drink("Orange juice")
# => "Orange juice"
CastleDinner.replace_drink("Tea")
# => "Apple juice"
Зареєструйтеся на Exercism, щоб вивчати й опановувати Crystal, а також 26 концепцій142 вправи та справжнє наставництво від людей, і все це безкоштовно.