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

Jua*_*eni 1 rust

使用match(如中的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));
}
Run Code Online (Sandbox Code Playgroud)

但是,提早返回(例如in foo)会大大减少代码嵌套的样子。如果多次必须解开选项或返回错误,则类似bar这样的代码会非常嵌套...

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

Mic*_*ail 6

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

ok_or?

我们可以将Optiona 转换为Result具有所需错误的a,然后立即将其与?运算符解开。此解决方案可能提供最小的缩进,并且可以轻松地用于“解包”多个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)
}
Run Code Online (Sandbox Code Playgroud)

这将评估内部错误,ok_or而不管是否实际使用它。如果此计算昂贵,ok_or_else则延迟产生错误的方法将更加有效(相关问题)。

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @kevlarr 您可以将“?”与“选项”一起使用,它将它们与“结果”混合在一起,这有点尴尬。在夜间,您可以 `impl From&lt;NoneError&gt; for MyError` 并启用 `try_trait` 功能,它将起作用。我想,大多数错误处理库也为此提供了很好的帮助器 - 我主要是一个“snafu”用户,请参阅其文档中的“OptionExt”。 (3认同)
  • 哇...我没有意识到?有选项...叹息..谢谢! (2认同)

Dus*_*tin 6

从 Rust 1.65 开始,您可以使用let-else 语句

fn bar3(x: Option<u64>) -> Result<u64, MyErrors> {
    let Some(x) = x else {
        return Err(MyErrors::SomeError);
    };
    Ok(x * 2)
}
Run Code Online (Sandbox Code Playgroud)