【发布时间】:2021-09-17 06:45:02
【问题描述】:
tl;dr 是否可以扩展 std::result::Result 以添加我自己的变体来表示“事情还好,但也......”并保留 impl Result 方法,如 @987654328 @?
我想扩展 Result 以指示函数调用者可用于特殊情况的其他状态。
use std::result::Result
use std::io::Error;
/// Extend Result to also signal "things are okay but check on things"
enum ResultExt<T, E> {
Result<T, E>,
OkButCheckThings(T),
}
pub fn do_stuff() -> ResultExt<u64, Error> {
// ...
}
pub fn main() -> {
let var = match do_stuff() {
Ok(val) => { val },
Err(err) => { 0 },
OkButCheckThings(val) => { check_things(); val },
}
dbg!(var);
}
它是possible to plainly extend an Enum。 但我也想使用底层的Result<T, E> 函数,例如is_ok。
let var2 = do_stuff();
if var2.is_ok() {
println!("It is totally Ok, nothing to check!");
}
我创建了一个rust playground example,它成功地扩展了Result<T, E>,但是扩展的enum 不能使用像is_ok() 这样的函数。
实际用例是一个调用 std::io::Read 的函数,可能需要“修改”返回的 Result 以指示除 Ok 和 Err 之外的其他状态。但我希望这些不同的“元状态”被一个enum 捕获,而不是返回各种其他bool 标志(我想避免使用(Result<T>, bool, bool) 返回签名。这将允许一个干净的match 声明所有可能的状态;Ok、Err、"Okay but..."、"Err but ..." 等。
【问题讨论】:
-
看来你要的是
Result<YourOwnResultEnum, Error> -
您好,这个可以帮上忙吗? stackoverflow.com/questions/25214064/…
-
我在问题中提到了stackoverflow.com/questions/25214064/…。它与这个问题不同。我想扩展
Enum并且仍然使用impl ...函数。 -
您不会想要这样,因为该方法不再正确。例如。
is_ok是通过检查Ok大小写来实现的,而is_err是通过返回!self.is_ok()来实现的。因此,如果您可以扩展Result并“继承其方法”,那么您最终会得到不正确的方法,因为is_err将为您的新的非错误案例返回 true。当然,is_err可以通过其他方式实现以使其工作,但关键是扩展enums 不可能对所有方法都有意义。另一个简单的例子:继承的transpose应该在扩展的Result上做什么?