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