gpt4 book ai didi

rust - 匹配结果类型时提早退出

转载 作者:行者123 更新时间:2023-12-03 11:35:59 24 4
gpt4 key购买 nike

我有一个参数类型为Result的方法。我非常喜欢链接,所以我在参数上使用了and_then。在某个时候,我想有条件地从and_then内部返回整个方法(因此有可能调用另一个and_then方法):

enum Good {
Ok,
Good,
VeryGood,
}
enum Pizza {
Tomato,
Pineapple,
}
enum Burger {
Cow,
}

enum Food {
Pizza(Pizza),
Burger(Burger),
}

fn main() {}

fn s(r: Result<Good, ()>) -> Result<Food, ()> {
r.and_then(|o| {
match o {
// Should be called in the next and_then block
Good::Ok => Ok(Pizza::Tomato),
// Should be called in the next and_then block
Good::Good => Ok(Pizza::Pineapple),
Good::VeryGood => {
// I am done. Don't call the next and_then block, but rather return the whole value to the caller.
return Ok(Food::Burger(Burger::Cow));
}
}
})
.and_then(|p: Pizza| {
// At this point, the closure input value should be pizza, because that's the only returned value
Ok(Food::Pizza(p))
})
}

Playground

我遇到各种编译器错误:

error[E0308]: mismatched types
--> src/main.rs:30:27
|
30 | return Ok(Food::Burger(Burger::Cow));
| ^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Pizza`, found enum `Food`
|
= note: expected type `Pizza`
found type `Food`

我希望有一种方法可以对其进行编译。我可以分解该方法并摆脱 and_then,但是也许 and_then有办法。

在我的真实代码中,我有更多的 and_then,它们将类型映射到其他类型,错误映射等,因此这是我面临的问题的简化再现路径。

这是我的代码库中粘贴粘贴的代码,显示了多个 and_then。我将错误从外部库映射到​​我自己的错误类型,因此如果有错误,则可以自动返回错误。我想继续更改从 and_then获得的类型,以便最终可以得到 User类型(尽管目前无法正常工作)。一种选择是不链接块并创建单独的值,但我希望可以直接将值返回给闭包内的调用方。
db_session
.query_with_values(query, values)
.map_err(|e| {
error!("{:?}", e);
TechnicalServerError::SERVER_RETRY
})
.and_then(|f| {
f.get_body().map_err(|e| {
error!("{:?}", e);
TechnicalServerError::SERVER_RETRY
})
})
.and_then(|b| b.into_rows().ok_or(TechnicalServerError::SERVER_RETRY))
.and_then(|mut c| {
if let Some(row) = c.pop() {
User::try_from_row(row).map_err(|e| {
error!("{:?}", e);
TechnicalServerError::SERVER_INVALID
})
} else {
return Ok(Login::Other(LoginResult::UNKNOWN_USER));
}
})
.and_then(|u| {
// 'u' should be of type 'user' at this point
// some user code here...
})

最佳答案

查看您编辑过的示例,我创建了一个approximate example:

// ...
.and_then(|b| b.into_rows().ok_or(TechnicalServerError::SERVER_RETRY))
.and_then(|mut c| {
if let Some(row) = c.pop() {
User::try_from_row(row).map_err(|e| {
error!("{:?}", e);
TechnicalServerError::SERVER_INVALID
})
} else {
return Ok(Login::Other(LoginResult::UNKNOWN_USER))
}
}).and_then(|u| {
// 'u' should be of type 'user' at this point
// some user code here...

我认为 and_then的作用有一个基本的误解。
  • and_then带有一个Result<T, E>,以及一个将T转换为Result<U, E>(即FnOnce(T) -> Result<U, E>)的函数。当您想要同时操作Ok(val)Error时,例如,您想更改错误的重映射并进行一些值处理时,请使用此功能。
  • map包含一个Result<T, E>和一个将T转换为另一个值U(即FnOnce(T) -> U)的函数。当您想更改Ok(val)而不影响Error部分时,请使用此选项。

  • 您说要更改用户,这可能是这样的:

    db_session
    .query_with_values(true)
    .map_err(|e| {
    println!("{:?}", e);
    MyError::ServerRetry
    })
    .and_then(|f| f.get_body(true).map_err(|e2|{
    println!("{:?}", e2);
    MyError::ServerRetry
    }))
    .and_then(|b| b.into_rows(true).ok_or(MyError::ServerRetry))
    .and_then(|mut c|{
    if let Some(row) = c.pop() {
    User::from_row(row).map_err(|e3| {
    println!("{:?}", e3);
    MyError::ServerRetry
    })
    } else {
    return Ok(User{ name: "X".to_string()})
    }
    })
    .map(|mut user| {
    user.name = "CHANGED".to_string();
    user
    });

    Rust playground

    但是,如您所见,查询的值将始终为 Result<User, Error>,直接操作该值的唯一方法是对 unwrap进行操作,但是如果遇到错误,则会感到 panic 。或者,您可以使用 if let来获取值而不会 panic 。

    关于rust - 匹配结果类型时提早退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59548004/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com