Rust代码示例——18.5.1.从Option中生成Result

处理混合错误中基本的方法就是将其互相嵌套。

use std::num::ParseIntError;


fn double_first(vec: Vec<&str>) -> Option<Result<i32, ParseIntError>> {

    vec.first().map(|first| {

        first.parse::<i32>().map(|n| 2 * n)

    })

}


fn main() {

    let numbers = vec!["42", "93", "18"];

    let empty = vec![];

    let strings = vec!["tofu", "93", "18"];


    println!("The first doubled is {:?}", double_first(numbers));


    println!("The first doubled is {:?}", double_first(empty));

    // Error 1: the input vector is empty


    println!("The first doubled is {:?}", double_first(strings));

    // Error 2: the element doesn't parse to a number

}

有时我们希望遇到错误时停止处理(例如使用?),但当Option为None时继续执行。这时transpose函数就能起到作用了,它可以交换Result和Option的位置。

use std::num::ParseIntError;


fn double_first(vec: Vec<&str>) -> Result<Option<i32>, ParseIntError> {

    let opt = vec.first().map(|first| {

        first.parse::<i32>().map(|n| 2 * n)

    });


    opt.transpose()

}


fn main() {

    let numbers = vec!["42", "93", "18"];

    let empty = vec![];

    let strings = vec!["tofu", "93", "18"];


    println!("The first doubled is {:?}", double_first(numbers));

    println!("The first doubled is {:?}", double_first(empty));

    println!("The first doubled is {:?}", double_first(strings));

}
代码解析
问题背景

代码需要处理两种不同的“空”或“错误”情况:

  1. Option::None:表示值不存在(例如:从一个空向量中获取第一个元素)。这通常不被视为一个需要终止程序的严重错误,程序逻辑可以继续处理这种情况。
  2. Result::Err:表示操作失败(例如:将一个字符串解析为整数时失败)。这通常是一个需要传播的错误,我们希望立即停止当前操作并返回这个错误。
?操作符行为

?操作符对Result和Option的行为不同:

在Result上使用?:如果是Ok(value),则解包value;如果是Err(e),则立即从当前函数返回Err(e)。

在Option上使用?:如果是Some(value),则解包出value;如果是None,则立即从当前函数返回None。

在这个场景中,我们不希望遇到None时就立即返回(停止函数),而是希望将它转换为Ok(None)。直接使用?无法实现这个目标。

transpose方法的使用

这正是transpose方法的用武之地。它用于转换嵌套的容器类型。具体在这里:

  1. 转换前:opt的类型是Option<Result<i32,ParseIntError>>。这个类型意味着:我们有一个可能的值(Option),而这个值本身又是一个可能出错的操作结果(Result)。
  2. 转换后:opt.transpose()返回的类型是Result<Option<i32>,ParseIntError>。这个类型意味着:这个操作的结果可能是一个出错的结果(Result)。如果没有错误,这个值可能是Option<i32>。

transpose的转换规则:

如果opt是Some(Ok(value))->返回Ok(Some(value))

如果opt是Some(Err(e))->返回Err(e),遇到错误,立即停止

如果opt是None->返回Ok(none),遇到None,继续处理,将其包装成成功的结果。

这完美地实现了我们的需求:错误(Err)导致提前返回,而空值(None)则被保留并继续处理。

原文链接:https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/option_result.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值