Выбрать главу

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Паника в предыдущем примере делает код ненадёжным. Обычно, мы хотим вернуть ошибку вызывающей стороне, чтобы уже она решала, как с ней поступить.

Первое, что нам нужно знать - это с каким типом ошибки мы работаем. Для определения типа Err, мы посмотрим на parse(), реализованную с типажом FromStr для i32. В результате, тип Err указан как ParseIntError.

В примере ниже, простой match делает код более громоздким.

use std::num::ParseIntError;

// Мы используем сопоставление с образцом без `unwrap()` и меняем тип результата.

fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {

match first_number_str.parse::<i32>() {

Ok(first_number) => {

match second_number_str.parse::<i32>() {

Ok(second_number) => {

Ok(first_number * second_number)

},

Err(e) => Err(e),

}

},

Err(e) => Err(e),

}

}

fn print(result: Result<i32, ParseIntError>) {

match result {

Ok(n) => println!("n равно {}", n),

Err(e) => println!("Ошибка: {}", e),

}

}

fn main() {

// Это даёт разумный ответ.

let twenty = multiply("10", "2");

print(twenty);

// Следующее теперь предоставляет более понятное сообщение об ошибке.

let tt = multiply("t", "2");

print(tt);

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

К счастью, map, and_then многие другие комбинаторы Option также реализованы и для Result. Документация по Result содержит полный их список.

use std::num::ParseIntError;

// Как и с `Option`, мы можем использовать комбинаторы, как `map()`.

// Эта функция в основном идентична предыдущей и читается как:

// изменяем n при валидном значении, иначе передаём ошибку.

fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> {

first_number_str.parse::<i32>().and_then(|first_number| {

second_number_str.parse::<i32>().map(|second_number| first_number * second_number)

})

}

fn print(result: Result<i32, ParseIntError>) {

match result {

Ok(n) => println!("n равно {}", n),

Err(e) => println!("Ошибка: {}", e),

}

}

fn main() {

// Это даёт разумный ответ.

let twenty = multiply("10", "2");

print(twenty);

// Следующее теперь предоставляет более понятное сообщение об ошибке.

let tt = multiply("t", "2");

print(tt);

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Как насчёт случая, когда мы хотим использовать конкретный тип Result много раз? Напомним, что Rust позволяет нам создавать псевдонимы. Мы можем удобно объявить псевдоним для конкретного Result.

Особенно полезным может быть создание псевдонимов на уровне модулей. Ошибки, найденные в конкретном модуле, часто имеют один и тот же тип Err, поэтому один псевдоним может лаконично объявить все ассоциированные Results. Это настолько полезно, что библиотека std обеспечивает даже один: io::Result!

Ниже приведён краткий пример для демонстрации синтаксиса:

use std::num::ParseIntError;

// Объявим обобщённый псевдоним для `Result` с типом ошибки `ParseIntError`.

type AliasedResult<T> = Result<T, ParseIntError>;