期权类型和早期回报。 is_none()时返回错误

问题描述 投票:1回答:1

使用匹配(如bar)似乎是一种常见的方法..

#[derive(Debug)]
pub enum MyErrors {
    SomeError,
}

fn foo(x: Option<u64>) -> Result<u64, MyErrors> {
    if x.is_none() {
      return Err(MyErrors::SomeError);
    } 

    // .. some long code where more options
    // are checked and matched 
    // The ok here is just so the code is simple and compiles
    Ok(x.unwrap() * 2)
}

fn bar(x: Option<u64>) -> Result<u64, MyErrors> {
    match x {
        None => {
            return Err(MyErrors::SomeError)?;
        }
        Some(v) => {
           // .. some long code where more options
           // are checked and matched 
           // The ok here is just so the code is simple and compiles
           Ok(x.unwrap() * 2)
        }
    }
}


fn main() {
    foo(Some(1));
    bar(Some(2));
}

但是,早期返回(例如在foo中)会显着减少代码嵌套的方式。如果有多次必须打开选项或返回错误,像bar这样的代码会非常嵌套...

在空选项的情况下,提前返回错误的建议做法是什么?

rust
1个回答
6
投票

如果由于内部复杂的逻辑而不希望使用更长的方法链,那么仍然存在一些可读的低缩进选项。

ok_or and ?

我们可以将Option转换为具有所需误差的Result,并立即用?算子打开它。该解决方案可能提供尽可能少的缩进,并且可以容易地用于“展开”多个Options。

fn bar1(x: Option<u64>) -> Result<u64, MyErrors> {
    let x = x.ok_or(MyErrors::SomeError)?;
    // A lot of stuff going on.
    Ok(x * 2)
}

这将评估ok_or中的错误,无论它是否实际使用。如果这个计算是昂贵的,那么懒惰地产生错误的ok_or_else将更有效(related question)。

if let

如果嵌套,此解决方案仍然可以导致代码阶梯,但如果else分支逻辑更复杂,则可能更合适。

fn bar2(x: Option<u64>) -> Result<u64, MyErrors> {
    if let Some(x) = x {
        // Lot of stuff here as well.
        Ok(x * 2)
    } else {
        Err(MyErrors::SomeError)
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.