Option и unwrap
В последнем примере мы показали, что можем вызвать сбой программы по своему желанию. Мы сказали нашей программе вызвать panic, если мы выпьем сладкий лимонад. Но что, если ожидаем какой-то напиток, но не получаем его? Этот случай тоже плохой, так что и он должен быть обработан!
Мы могли бы сравнить значение с пустой строкой ("") так же, как мы сделали это с лимонадом. Поскольку мы используем Rust, пусть компилятор сам укажет нам случаи, когда напитка нет.
Перечисление (enum) из стандартной библиотеки (std), называющееся Option<T>, используется, когда значение может отсутствовать. Оно может находиться в одном из двух состояний:
Some(T): элемент типаTнайденNone: элемент не найден
Эти случаи могут быть или явно обработаны с помощью match, или неявно с unwrap. Неявная обработка либо вернёт внутренний элемент, либо вызовет panic.
Обратите внимание, что можно вручную настроить сообщение выдаваемое при панике с помощью expect, в противном случае unwrap оставляет нам менее понятный вывод, чем явная обработка. В следующем примере явная обработка даёт более контролируемый результат, при этом сохраняется возможность паниковать, если это необходимо.
// Взрослый человек всё это видео, и может хорошо справиться с любым напитком.
// Все напитки обрабатываются явно, с использованием конструкции `match`.
fn give_adult(drink: Option<&str>) { // выдать взрослому напиток
// Укажем что нужно делать, в каждом случае.
match drink {
Some("лимонад") => println!("Фи! Слишком сладко."),
Some(inner) => println!("{}? Хорошо.", inner),
None => println!("Нет напитка? Ну что ж."),
}
}
// Другие будут паниковать перед тем как выпить напитки, содержащие сахар.
// Все напитки обрабатываются неявно, с использованием `unwrap`.
fn drink(drink: Option<&str>) {
// `unwrap` возвращает `panic` когда получает на вход `None`.
let inside = drink.unwrap();
if inside == "лимонад" { panic!("AAAaaaaa!!!!"); }
println!("Я люблю {}ы!!!!!", inside);
}
fn main() {
let water = Some("вода");
let lemonade = Some("лимонад");
let void = None;
give_adult(water);
give_adult(lemonade);
give_adult(void);
let coffee = Some("кофе");
let nothing = None;
drink(coffee);
drink(nothing);
}