使用组合器简化 Rust 匹配
Simplifying Rust matching with combinators
我有这样的东西:
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
值做任何事情,只是打印错误是来自 fnX
还是 fnY
.
你不需要这样的"combinator"。
fnX
接受类型为 Result<(), X>
和 returns 的参数 Result<(), Y>
当代码比较复杂时,将表达式分开可能有助于提高可读性。
let result = fnY(x);
match fnX(result).await {
Ok(v) => {
// here v is ok value, in this case ()
}
Err(e) => error!("error = {}", e),
};
我假设你想简化这样的事情(删除与问题无关的 .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
箱子的作者。
我有这样的东西:
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
值做任何事情,只是打印错误是来自 fnX
还是 fnY
.
你不需要这样的"combinator"。
fnX
接受类型为 Result<(), X>
和 returns 的参数 Result<(), Y>
当代码比较复杂时,将表达式分开可能有助于提高可读性。
let result = fnY(x);
match fnX(result).await {
Ok(v) => {
// here v is ok value, in this case ()
}
Err(e) => error!("error = {}", e),
};
我假设你想简化这样的事情(删除与问题无关的 .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
箱子的作者。