fn main() {
// Это даёт разумный ответ.
let twenty = multiply("10", "2");
print(twenty);
// Следующее теперь предоставляет более понятное сообщение об ошибке.
let tt = multiply("t", "2");
print(tt);
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Псевдонимы дляResult
Как насчёт случая, когда мы хотим использовать конкретный тип Result много раз? Напомним, что Rust позволяет нам создавать псевдонимы. Мы можем удобно объявить псевдоним для конкретного Result.
Особенно полезным может быть создание псевдонимов на уровне модулей. Ошибки, найденные в конкретном модуле, часто имеют один и тот же тип Err, поэтому один псевдоним может лаконично объявить все ассоциированные Results. Это настолько полезно, что библиотека std обеспечивает даже один: io::Result!
Ниже приведён краткий пример для демонстрации синтаксиса:
use std::num::ParseIntError;
// Объявим обобщённый псевдоним для `Result` с типом ошибки `ParseIntError`.
type AliasedResult = Result;
// Используем вышеуказанный псевдоним для обозначения
// нашего конкретного типа `Result`.
fn multiply(first_number_str: &str, second_number_str: &str) -> AliasedResult {
first_number_str.parse::().and_then(|first_number| {
second_number_str.parse::().map(|second_number| first_number * second_number)
})
}
// Здесь псевдоним снова позволяет нам сэкономить место.
fn print(result: AliasedResult) {
match result {
Ok(n) => println!("n это {}", n),
Err(e) => println!("Ошибка: {}", e),
}
}
fn main() {
print(multiply("10", "2"));
print(multiply("t", "2"));
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Смотрите также:
io::Result
Ранний выход
В предыдущем примере мы явно обработали ошибки при помощи комбинаторов. Другой способ сделать это - использовать комбинацию выражения match и раннего выхода.
Таким образом мы просто можем остановить работу функции и вернуть ошибку, если она произошла. Для некоторых, такой код будет легче в чтении и написании. Посмотрите код из предыдущего примера, переписанный с использованием раннего выхода:
use std::num::ParseIntError;
fn multiply(first_number_str: &str, second_number_str: &str) -> Result {
let first_number = match first_number_str.parse::() {
Ok(first_number) => first_number,
Err(e) => return Err(e),
};
let second_number = match second_number_str.parse::() {
Ok(second_number) => second_number,
Err(e) => return Err(e),
};
Ok(first_number * second_number)
}
fn print(result: Result) {
match result {
Ok(n) => println!("n равно {}", n),
Err(e) => println!("Ошибка: {}", e),
}
}
fn main() {
print(multiply("10", "2"));
print(multiply("t", "2"));
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
На данный момент, мы изучили обработку ошибок при помощи комбинаторов и раннего выхода. Мы хотим избежать паники, но явная обработка всех ошибок достаточно громоздка.
В следующем разделе, мы познакомимся с ? для случаев, где нам просто хотим сделать unwrap без возможности вызова panic.
Представляем:?
Иногда мы хотим получить простоту unwrap, но без panic. До текущего момента unwrap заставлял нас делать всё больше и больше, в то время как мы хотели только извлечь переменную. Для этих целей был введён ?.
При обнаружении Err, можно выполнить два действия:
1. panic!, который мы решили по возможности избегать
2. return так как возврат Err говорит о том, что мы её не обрабатывали
? почти1 эквивалентен unwrap, который при Err делает return вместо panic. Давайте посмотрим как мы можем упростить наш пример, использующий комбинаторы:
use std::num::ParseIntError;
fn multiply(first_number_str: &str, second_number_str: &str) -> Result {
let first_number = first_number_str.parse::()?;
let second_number = second_number_str.parse::()?;
Ok(first_number * second_number)
}
fn print(result: Result) {
match result {
Ok(n) => println!("n равно {}", n),
Err(e) => println!("Ошибка: {}", e),
}
}
fn main() {
print(multiply("10", "2"));
print(multiply("t", "2"));
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Макросtry!
До появления ?, аналогичная функциональность была доступна через макрос try!. Сейчас рекомендуется использовать оператор ?, но вы до сих пор можете найти try!, когда просматриваете старый код. Функция multiply из предыдущего примера с использованием try! будет выглядеть следующим образом: