为什么我们使用选项枚举?



我不明白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

也许上面的例子不是一个很好的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 编程语言中的另一个示例:

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)plus_one体中的变量x将具有 值Some(5).然后,我们将它与每个比赛臂进行比较。

None => None,

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

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

Some(5)匹配Some(i)吗?为什么是这样!我们有相同的变体。这i绑定到Some中包含的值,所以i取值5。这 然后执行匹配臂中的代码,因此我们将 1 加到i的值和 用我们的总6创造新的Some价值。

现在让我们考虑示例 6-5 中plus_one的第二次调用,其中xNone.我们进入match并与第一臂进行比较。

None => None,

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

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

使用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)
}
}

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

返回enum是对返回未包装的魔术值的改进,因为对程序员来说,返回值可能与他们想要的函数不同。

最新更新