为什么我们使用Option枚举?

时间:2019-06-08 07:07:44

标签: enums rust

我不了解Option枚举的用途。我读到Rust没有空值。 Option枚举的定义如下:

enum Option<T> {
    Some(T),
    None,
}

我阅读了它的实现,并遇到了以下示例:

fn main() {
    fn divide(numerator: f64, denominator: f64) -> Option<f64> {
        if denominator == 0.0 {
            None
        } else {
            Some(numerator / denominator)
        }
    }

    // The return value of the function is an option
    let result = divide(2.0, 3.0);

    // Pattern match to retrieve the value
    match result {
        // The division was valid
        Some(x) => println!("Result: {}", x),
        // The division was invalid
        None => println!("Cannot divide by 0"),
    }
}

当他们也可以这样做时:

fn main() {
    fn divide(numerator: f64, denominator: f64) -> String {
        if denominator == 0.0 {
            format!("Can't divide")
        } else {
            let x = numerator / denominator;
            format!("{}", x)
        }
    }

    let result = divide(2.0, 3.0);
    println!("{}", result);
}

两个程序的输出:

0.6666666666666666

2 个答案:

答案 0 :(得分:1)

也许上面的示例不是Option的很好示例,但是下面的示例显示了Option的最佳状态:

fn main() {
    let name = String::from("naufil");
    println!(
        "Character at index 6: {}",
        match name.chars().nth(6) {
            Some(c) => c.to_string(),
            None => "No character at index 6!".to_string(),
        }
    )
}

当我们不确定在第6个元素处是否有字符并且您不希望程序崩溃时,Option就可以解决。这是The Rust Programming Language中的另一个示例:

  
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);
     

清单6-5:在{上使用match表达式的函数   一个Option<i32>

     

让我们更详细地检查plus_one的首次执行。当我们打电话   plus_one(five)x正文中的变量plus_one将具有   值Some(5)。然后,我们将其与每个比赛手臂进行比较。

None => None,
     

Some(5)的值与模式None不匹配,因此我们继续   下一臂。

Some(i) => Some(i + 1),
     

Some(5)Some(i)匹配吗?为什么会呢!我们有相同的变体。的   i绑定到Some中包含的值,因此i采用值5。的   然后执行匹配臂中的代码,因此我们将i的值加1,然后   创建一个新的Some值,其中的总数为6

     

现在让我们考虑清单6-5中第二次调用plus_one,其中x是   None。我们输入match并与第一个手臂进行比较。

None => None,
     

匹配!没有要添加的值,因此程序会停止并返回   None右侧的=>值。因为第一只手臂匹配,没有其他   比较武器。

     

在许多情况下,将match和枚举组合起来很有用。你会看到这个   在Rust代码中使用很多模式:match对一个枚举,将变量绑定到   数据,然后基于它执行代码。一开始有点棘手,但是   一旦习惯了,就希望您能使用所有语言。它的   始终是用户的最爱。

答案 1 :(得分:0)

使用Option enum的原因与使用Result枚举的原因相同。它使程序员可以看到他们可能会收到的返回值的广度,但是无需深入研究代码,您就不会记住或从未见过的所有细节。

Option不是一个特殊的值,它只是一个枚举,例如Result。您还可以使用类似的内容:

enum Division_Result {
    Successful(f64),
    DividedByZero,
}

fn divide(numerator: f64, denominator: f64) -> Division_Result {
    if denominator == 0.0 {
        Division_Result::DividedByZero
    } else {
        Division_Result::Successful(numerator / denominator)
    }
}

碰巧的是,可选值是您在程序中必须处理的一些最常见的值类型。他们将Optional枚举烘焙为标准,因为否则,您将不得不面对每个提出自己的enum的人,以获取Optional值的简单概念。

返回enum是对返回未包装魔术值的一种改进,因为对于程序员而言,更明确的是,返回值可能与他们想要的功能有所不同。