【问题标题】:Simplifying Rust matching with combinators使用组合器简化 Rust 匹配
【发布时间】:2020-03-18 04:56:16
【问题描述】:

我有这样的事情:

match fnX(
    fnY(x), // Returns Result<(), X>
) // Returns Result<(), Y>
.await
{
    Ok(v) => {
        if v.is_err() {
            error!("error = {}", v);
        }
    }
    Err(e) => error!("error = {}", e),
};

我怎样才能用组合器写这个,这样我只需要error! 一次?我不想对Ok 值做任何事情,只要打印错误来自fnXfnY

【问题讨论】:

  • 期望真的不清楚,你怎么能从一个返回Result&lt;(), Y&gt;的函数中得到v.is_err()?这是没有意义的,根据定义v 将是(),它没有is_errfnX() 真的将Result&lt;(), X&gt; 作为输入吗?

标签: error-handling rust pattern-matching


【解决方案1】:

我假设您的意思是简化这样的事情(删除与问题无关的 .await):

match fnX(x) { // Returns Result<X, EX>
    Ok(y) => match fnY(y) { // Returns Result<Y, EY>
        Ok(_) => println!("Success!"),
        Err(e) => error!("error = {}", e),
    },
    Err(e) => error!("error = {}", e),
}

如果错误类型相同,可以用and_then简化代码:

match fnX(x).and_then(fnY) {
    Ok(_) => println!("Success!"),
    Err(e) => error!("error = {}", e),
}

如果错误类型不同,可以使用map_err将其转换为单一类型:

match fnX(x)
    .map_err(MyError::from)
    .and_then(|y| fnY(y).map_err(MyError::from))
{
    Ok(_) => println!("Success!"),
    Err(e) => error!("error = {}", e),
}

后者可以使用map_for crate 的最新开发版本进行简化:

match map_for!(y <- fnX (x);
               v <- fnY (y);
               => v)
{
    Ok(_) => println!("Success"),
    Err(e @ MyError { .. }) => error!("error = {}", e),
}
  • 请注意,仅当编译器无法自动推断错误类型时,才需要 @ MyError {..} 注释。
  • 完全免责声明:我是map_for crate 的作者。

【讨论】:

    【解决方案2】:

    你不需要这样的“组合器”。

    fnX 接受Result&lt;(), X&gt; 类型的参数并返回Result&lt;(), Y&gt;

    当代码复杂时,它可能有助于分离表达式,使其更具可读性。

    let result = fnY(x);
    match fnX(result).await {
        Ok(v) => {
            // here v is ok value, in this case ()
        }
        Err(e) => error!("error = {}", e),
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      相关资源
      最近更新 更多