Rust 匹配结果类型时提前退出
我有一个参数类型为Rust 匹配结果类型时提前退出,rust,Rust,我有一个参数类型为Result的方法。我非常喜欢链接,所以我在参数上使用和_-then。在某个时候,我想有条件地从和_-then内部返回整个方法(因此有可能调用另一个和_-then方法): 我希望有办法让它编译。我可以分解这个方法,去掉和_then,但可能有一种方法可以使用和_then 在我的真实代码中,我有更多的和_-then,它们将类型映射到其他类型、错误映射等,因此这是我所面临问题的简化再现路径 这是从我的代码库复制粘贴的代码,显示多个和_然后。我正在将外部库中的错误映射到我自己的错误类型
Result
的方法。我非常喜欢链接,所以我在参数上使用和_-then
。在某个时候,我想有条件地从和_-then
内部返回整个方法(因此有可能调用另一个和_-then
方法):
我希望有办法让它编译。我可以分解这个方法,去掉和_then
,但可能有一种方法可以使用和_then
在我的真实代码中,我有更多的和_-then
,它们将类型映射到其他类型、错误映射等,因此这是我所面临问题的简化再现路径
这是从我的代码库复制粘贴的代码,显示多个和_然后
。我正在将外部库中的错误映射到我自己的错误类型中,因此如果存在错误,可以自动返回错误。我想不断更改我从和_然后
获得的类型,以便最终获得类型用户
(尽管它目前不起作用)。一个选项是不链接块并创建单独的值,但我希望可以在闭包中直接将值返回给调用方
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...
})
不是干净的。不如改成
?
fn s(r: Result<Good, ()>) -> Result<Food, ()> {
let p = match r? {
// Should be called in the next and_then block
Good::Ok => Pizza::Tomato,
// Should be called in the next and_then block
Good::Good => Pizza::Pineapple,
Good::VeryGood => {
return Ok(Food::Burger(Burger::Cow));
},
};
Ok(Food::Pizza(p))
}
fns(r:Result)->Result{
让p=匹配r{
//应在下一个和_然后块中调用
好的::好的=>比萨饼::西红柿,
//应在下一个和_然后块中调用
好的::好的=>比萨饼::菠萝,
好的::VeryGood=>{
返回Ok(食物:汉堡(汉堡:牛));
},
};
Ok(食物:比萨饼(p))
}
查看您编辑的示例,我创建了一个:
/。。。
,然后(|b | b.进入_行().ok_或(TechnicalServerError::SERVER_RETRY))
.然后| mut c |{
如果让一些(行)=c.pop(){
用户::try_from_row(row).map_err(| e |{
错误!(“{:?}”,e);
TechnicalServerError::服务器\u无效
})
}否则{
返回Ok(登录::其他(登录结果::未知用户))
}
}).然后| u |{
//此时,“u”应为“用户”类型
//这里有一些用户代码。。。
我认为人们对和_then
的作用有一个基本的误解
获取一个和_然后
,以及一个将结果
转换为T
(即结果
)的函数。当您想要同时操作FnOnce(T)->结果
和Ok(val)
时,可以使用该函数,例如,您想要更改重新映射错误并进行一些值处理错误
获取一个map
和一个将结果
转换为另一个值T
(即U
)的函数。当您想要更改FnOnce(T)->U
而不影响Ok(val)
部分时,请使用此函数错误
db\u会话
.使用_值查询_(true)
.map|u err(| e|{
println!(“{:?}”,e);
MyError::服务器重试
})
。然后(| f | f.get_body(true)。映射错误(| e2|{
println!(“{:?}”,e2);
MyError::服务器重试
}))
.和|然后(| b | b.进入|行(true)。确定_或(MyError::ServerRetry))
.然后| mut c|{
如果让一些(行)=c.pop(){
用户::from_row(row).map_err(| e3 |{
println!(“{:?}”,e3);
MyError::服务器重试
})
}否则{
返回Ok(用户{name:“X.”to_string()})
}
})
.map(|多用户|{
user.name=“CHANGED.”to_string();
用户
});
但是,正如您所看到的,查询的值始终是
Result
,直接对该值进行操作的唯一方法是unwrap
,但如果遇到错误,它会崩溃。或者,您可以使用if let
来获得值,而不会崩溃。这在我提供的代码中确实有效:)然而,在我的“真实”代码中,我有更多的and_,它们映射类型和错误,遗憾的是,这种方式是不够的:(无论如何,谢谢你的回答,我会更新我的问题,使其更详细。)clear@J.Doe:那么,你能创建一个更真实的示例/显示真实的代码吗?你不能像那样使用返回
,因此任何替代方案都可能需要更多的上下文。(另外,这是针对稳定的锈迹还是#![feature]
s可以吗?)简单地说,我正在链接多个and_then's,有时,我只想说(在and_then块中):好的,如果某个值为真,只需将该值返回给调用者,否则只需调用next和_then。这是稳定的。总而言之:and then块中的return语句实际上不会返回函数,而是将给定类型映射到返回值,使其在next和_then块中可用?@J.Doe:return
returns fr对于作为参数传递给和_then
,是的。@J.Doe您能将示例更改为具有多个和_then
?您发布的代码没有编译。您能编辑它以更好地向我们展示工作流吗?另外,您为什么要提前返回?有具体原因吗?对我来说,使用用一个返回点映射
。@DanielFath请参阅我的编辑。您的问题似乎可以用的答案来回答。如果没有,请您的问题解释差异。否则,我们可以将此问题标记为已回答。您还应该阅读,其中讨论了如何使?
自动包装基本错误。
fn s(r: Result<Good, ()>) -> Result<Food, ()> {
let p = match r? {
// Should be called in the next and_then block
Good::Ok => Pizza::Tomato,
// Should be called in the next and_then block
Good::Good => Pizza::Pineapple,
Good::VeryGood => {
return Ok(Food::Burger(Burger::Cow));
},
};
Ok(Food::Pizza(p))
}