为什么.or_else()被公式化两次?

时间:2016-06-27 05:41:04

标签: error-handling rust

Result docs.or_else()方法提供以下说明:

  

fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F>

     

如果结果为Err则调用op,否则返回self的Ok值。

     

此功能可用于基于结果值的控制流程。

     

实施例

     

fn sq(x: u32) -> Result<u32, u32> { Ok(x * x) }

     

fn err(x: u32) -> Result<u32, u32> { Err(x) }

     

assert_eq!(Ok(2).or_else(sq).or_else(sq), Ok(2));

     

assert_eq!(Ok(2).or_else(err).or_else(sq), Ok(2));

     

assert_eq!(Err(3).or_else(sq).or_else(err), Ok(9));

     

assert_eq!(Err(3).or_else(err).or_else(err), Err(3));

认为可以用更多的空格解析or_else类型注释:

fn or_else<F,                           // F being the return type of the Result?
           O: FnOnce(E) -> Result<T, F> // the function to run instead if error
          > 
           (self, op: O)                // arguments to the `.or_else()` method
-> Result<T, F>                         // return type is again Result

假设我已经做到了,那是否意味着.or_else()只是给了Result Error,而op替换为Result函数的返回值?

我可以理解再次返回or_else(),因为可能错误抛出的代码下游的所有代码都被&#34;染色&#34;有进一步错误的可能性(并且由调用者来处理)。但为什么在例子中加倍调用呢?有几种不同的排列,但我不确定他们试图展示的是什么(或者这种加倍的Json模式是不是惯用的。)

1 个答案:

答案 0 :(得分:8)

该示例可能有点不幸,因为它试图同时显示or_else如何工作,以及为什么要使用它。

将其分成两部分。首先or_else实际上做了什么。如果您在Ok值上调用它,则会传递Ok值。如果在Err值上调用它,它将执行该函数。这个例子应该足够了:

Ok(2).or_else(sq), Ok(2) // not called
Ok(2).or_else(err), Ok(2) // not called
Err(2).or_else(sq), Ok(4) // called, succeeds
Err(2).or_else(err), Err(3) // called, fails

现在,你为什么要使用它呢?想象一下,你正在做一些有很多替代方法的操作。例如,您尝试在Linux上安装某个软件包,但不关心哪个软件包管理器可用 - 您只是打算强制它。所有返回Result<...>的函数都可以执行此操作:

install_with_apt().
    or_else(install_with_yum).
    or_else(install_with_pacman).
    or_else(install_with_dnf).
    or_else...

你知道如果你回来Ok,至少有一个成功了,如果你回来Err,所有这些都失败了。如果可能只是试图向您显示,则示例中加倍.or_else()用法可以轻松链接此调用。