Изучение перечисления Result в Rust

RustRustBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом практическом занятии мы исследуем перечисление Result в Rust, которое позволяет нам выражать успех или неудачу операции, возвращая либо Ok с значением, либо Err с объяснением причины неудачи.

Примечание: Если в практическом занятии не указано имя файла, вы можете использовать любое имя файла, которое хотите. Например, вы можете использовать main.rs, скомпилировать и запустить его с помощью rustc main.rs &&./main.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/MemorySafetyandManagementGroup(["Memory Safety and Management"]) rust(("Rust")) -.-> rust/DataStructuresandEnumsGroup(["Data Structures and Enums"]) rust(("Rust")) -.-> rust/ErrorHandlingandDebuggingGroup(["Error Handling and Debugging"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/DataTypesGroup -.-> rust/floating_types("Floating-point Types") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/MemorySafetyandManagementGroup -.-> rust/lifetime_specifiers("Lifetime Specifiers") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("Method Syntax") rust/ErrorHandlingandDebuggingGroup -.-> rust/panic_usage("panic! Usage") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99257{{"Изучение перечисления Result в Rust"}} rust/floating_types -.-> lab-99257{{"Изучение перечисления Result в Rust"}} rust/function_syntax -.-> lab-99257{{"Изучение перечисления Result в Rust"}} rust/expressions_statements -.-> lab-99257{{"Изучение перечисления Result в Rust"}} rust/lifetime_specifiers -.-> lab-99257{{"Изучение перечисления Result в Rust"}} rust/method_syntax -.-> lab-99257{{"Изучение перечисления Result в Rust"}} rust/panic_usage -.-> lab-99257{{"Изучение перечисления Result в Rust"}} rust/operator_overloading -.-> lab-99257{{"Изучение перечисления Result в Rust"}} end

Result

Мы видели, что перечисление Option может использоваться в качестве возвращаемого значения функций, которые могут завершиться неудачей, где None может быть возвращено для индикации неудачи. Однако, иногда важно выразить причину, по которой операция завершилась неудачей. Для этого существует перечисление Result.

Перечисление Result<T, E> имеет два варианта:

  • Ok(value), которое означает, что операция завершилась успешно, и оборачивает value, возвращаемое операцией. (value имеет тип T)
  • Err(why), которое означает, что операция завершилась неудачей, и оборачивает why, которое (надеюсь) объясняет причину неудачи. (why имеет тип E)
mod checked {
    // Математические "ошибки", которые мы хотим ловить
    #[derive(Debug)]
    pub enum MathError {
        DivisionByZero,
        NonPositiveLogarithm,
        NegativeSquareRoot,
    }

    pub type MathResult = Result<f64, MathError>;

    pub fn div(x: f64, y: f64) -> MathResult {
        if y == 0.0 {
            // Эта операция завершилась бы с `ошибкой`, вместо этого давайте вернем причину
            // неудачи, обернутую в `Err`
            Err(MathError::DivisionByZero)
        } else {
            // Эта операция корректна, возвращаем результат, обернутый в `Ok`
            Ok(x / y)
        }
    }

    pub fn sqrt(x: f64) -> MathResult {
        if x < 0.0 {
            Err(MathError::NegativeSquareRoot)
        } else {
            Ok(x.sqrt())
        }
    }

    pub fn ln(x: f64) -> MathResult {
        if x <= 0.0 {
            Err(MathError::NonPositiveLogarithm)
        } else {
            Ok(x.ln())
        }
    }
}

// `op(x, y)` === `sqrt(ln(x / y))`
fn op(x: f64, y: f64) -> f64 {
    // Это трехуровневый пирамидальный match!
    match checked::div(x, y) {
        Err(why) => panic!("{:?}", why),
        Ok(ratio) => match checked::ln(ratio) {
            Err(why) => panic!("{:?}", why),
            Ok(ln) => match checked::sqrt(ln) {
                Err(why) => panic!("{:?}", why),
                Ok(sqrt) => sqrt,
            },
        },
    }
}

fn main() {
    // Это завершится с ошибкой?
    println!("{}", op(1.0, 10.0));
}

Резюме

Поздравляем! Вы завершили практическое занятие по Result. Вы можете выполнить больше практических занятий в LabEx, чтобы улучшить свои навыки.