用 Result 包装非错误函数的惯用 Rust 方法是什么?
What's the idiomatic Rust way to wrap a non-error function with Result?
我有一个函数可以将 str
解析为一个数字并 returns 它或一个错误
fn parse_str<T: FromStr>(text: &str) -> Result<T, SaleError> {
match text.parse::<T>() {
Ok(value) => Ok(value),
_ => Err(SaleError::new(6010, 1999)),
}
}
SaleError
是我的自定义错误结构。
解析后,我想在结果值中做一些其他检查,例如,用is_sign_positive()
检查数字是否为正数,如果不是,我想发出一个Err(SaleError)
.
因为 is_sign_positive()
returns 只有一个 bool
,我所做的就是创建这个函数:
fn is_positive(number: f64) -> Result<f64, SaleError> {
match number.is_sign_positive() {
true => Ok(number),
false => Err(SaleError::new(6010, 1999)),
}
}
现在我可以像那样使用它了:
let value1 = try!(parse_str::<f64>("123").and_then(is_positive)
.or(Err(SaleError::new(6010, 1465))));
let value2 = try!(parse_str::<f64>("321").and_then(is_positive)
.or(Err(SaleError::new(6010, 5000))));
这很好用,但请注意,我想要 value1
和 value2
的特定 SaleError
实例,所以我使用了 or()
函数。
现在,因为我总是想要一个特定的错误而不是 is_positive
returns 对我来说,是否可以包装 is_sign_positive()
这样我就可以在不需要的情况下使用它创建函数 is_positive
.
类似的东西:
let value1 = try!(parse_str::<f64>("123").check_if(|n| n.is_sign_positive())
.or(Err(SaleError::new(6010, 1465))));
我可能只使用 if
:
"123"
.parse::<f64>()
.map_err(|_| SaleError(6010, 1999))
.and_then(|n| {
if n.is_sign_positive() {
Ok(n)
} else {
Err(SaleError(6010, 1465))
}
});
如果你真的想要它,你可以做到:
struct SaleError(i32, i32);
fn main() {
"123"
.parse::<f64>()
.map_err(|_| SaleError(6010, 1999))
.wonky(SaleError(6010, 1465), |n| n.is_sign_positive());
}
trait Wonky<T, E> {
fn wonky<F>(self, error: E, f: F) -> Result<T, E>
where F: FnOnce(&T) -> bool;
}
impl<T, E> Wonky<T, E> for Result<T, E> {
fn wonky<F>(self, error: E, f: F) -> Result<T, E>
where F: FnOnce(&T) -> bool
{
match self {
Ok(n) => if f(&n) { Ok(n) } else { Err(error) },
Err(e) => Err(e),
}
}
}
我有一个函数可以将 str
解析为一个数字并 returns 它或一个错误
fn parse_str<T: FromStr>(text: &str) -> Result<T, SaleError> {
match text.parse::<T>() {
Ok(value) => Ok(value),
_ => Err(SaleError::new(6010, 1999)),
}
}
SaleError
是我的自定义错误结构。
解析后,我想在结果值中做一些其他检查,例如,用is_sign_positive()
检查数字是否为正数,如果不是,我想发出一个Err(SaleError)
.
因为 is_sign_positive()
returns 只有一个 bool
,我所做的就是创建这个函数:
fn is_positive(number: f64) -> Result<f64, SaleError> {
match number.is_sign_positive() {
true => Ok(number),
false => Err(SaleError::new(6010, 1999)),
}
}
现在我可以像那样使用它了:
let value1 = try!(parse_str::<f64>("123").and_then(is_positive)
.or(Err(SaleError::new(6010, 1465))));
let value2 = try!(parse_str::<f64>("321").and_then(is_positive)
.or(Err(SaleError::new(6010, 5000))));
这很好用,但请注意,我想要 value1
和 value2
的特定 SaleError
实例,所以我使用了 or()
函数。
现在,因为我总是想要一个特定的错误而不是 is_positive
returns 对我来说,是否可以包装 is_sign_positive()
这样我就可以在不需要的情况下使用它创建函数 is_positive
.
类似的东西:
let value1 = try!(parse_str::<f64>("123").check_if(|n| n.is_sign_positive())
.or(Err(SaleError::new(6010, 1465))));
我可能只使用 if
:
"123"
.parse::<f64>()
.map_err(|_| SaleError(6010, 1999))
.and_then(|n| {
if n.is_sign_positive() {
Ok(n)
} else {
Err(SaleError(6010, 1465))
}
});
如果你真的想要它,你可以做到:
struct SaleError(i32, i32);
fn main() {
"123"
.parse::<f64>()
.map_err(|_| SaleError(6010, 1999))
.wonky(SaleError(6010, 1465), |n| n.is_sign_positive());
}
trait Wonky<T, E> {
fn wonky<F>(self, error: E, f: F) -> Result<T, E>
where F: FnOnce(&T) -> bool;
}
impl<T, E> Wonky<T, E> for Result<T, E> {
fn wonky<F>(self, error: E, f: F) -> Result<T, E>
where F: FnOnce(&T) -> bool
{
match self {
Ok(n) => if f(&n) { Ok(n) } else { Err(error) },
Err(e) => Err(e),
}
}
}