#try #unwrap #let #else

try_utils

The try! 宏深入到枚举变体中。它比 ? 和 unwrap() 更灵活,也可以与您的枚举一起使用!

2 个版本

使用旧的 Rust 2015

0.1.2 2023 年 3 月 9 日
0.1.0 2023 年 3 月 9 日

#997 in Rust 模式

Apache-2.0/MIT

15KB
219

The inner! 宏使深入到枚举变体变得更加方便。The some!ok! 宏将枚举转换为 OptionResult

Crates.io

API 文档

有用的 unwrap

最简单的情况几乎像 unwrap

let x = Some(1);
let y: Result<_, ()> = Ok(2);
assert_eq!(inner!(x), 1);
assert_eq!(inner!(y), 2);

...但如果你在 NoneErr 值上使用它

let z = None;
let y = inner!(z);

...它将引发 panic,错误消息将指向比 libcore 内部的某些行号更有用的位置

thread "test" panicked at "Unexpected value found inside "z"", src/lib.rs:23

错误处理

如果 panic 不是选项 - 通常都不是 - 只需添加一个 else 子句

let x: Result<String, i32> = Err(7);
let y = inner!(x, else { return });
// Since x is an Err, we'll never get here.
println!("The string length is: {}", y.len());

您可以使用 else 子句计算默认值,或使用流程控制(例如 breakcontinuereturn)。

想访问 else 子句中的 Err 值吗?没问题,只需在 else 后添加一个 |variable|,就像这样

let x: Result<String, i32> = Err(7);
let y = inner!(x, else |e| {
    assert_eq!(e, 7);
    (e + 2).to_string()
});
assert_eq!(&y, "9");

注意:这不会将您的 else 子句转换为闭包,因此您仍然可以像以前一样使用(例如)return

它与您的枚举也一起工作

它不仅与 OptionResult 一起工作。只需添加一个 if 子句

enum Fruit {
    Apple(i32),
    Orange(i16),
}

let z = Fruit::Apple(15);
let y = inner!(z, if Fruit::Apple, else {
    println!("I wanted an apple and I didn't get one!");
    0
});
assert_eq!(y, 15);

您可以省略 else 子句,以便在枚举不是预期变体时引发 panic。

请注意,在这种情况下,整个项目(而不是 Err 内的内容)被传递到 else 子句中

#[derive(Eq, PartialEq, Debug)]
enum Fruit {
    Apple(i32),
    Orange(i16),
}

let z = Fruit::Orange(15);
inner!(z, if Fruit::Apple, else |e| {
    assert_eq!(e, Fruit::Orange(15));
    return;
});

您还可以使用 Some 宏将您的枚举转换为 Option

assert_eq!(some!(Fruit::Apple(15), if Fruit::Apple), Some(15));
assert_eq!(some!(Fruit::Orange(5), if Fruit::Apple), None);
assert_eq!(some!(Fruit::Orange(5), if Fruit::Apple, else |e| {Some(e + 2)}), Some(7));

或使用 ok!() 宏转换为 Result

assert_eq!(ok!(Fruit::Apple(15), if Fruit::Apple), Ok(15));
assert_eq!(ok!(Fruit::Orange(5), if Fruit::Apple), Err(Fruit::Orange(5)));

assert_eq!(ok!(Fruit::Orange(5), if Fruit::Apple, or |e| {e + 70}), Err(75));
assert_eq!(ok!(Fruit::Orange(5), if Fruit::Apple, else {Err(75)}), Err(75));

请注意,宏ok!()有一个可选的or子句,它将表达式封装在Err中,而else子句则提供了最大的灵活性,允许返回ErrOk

另一个选项是为你的枚举实现这个crate的IntoResult特质。这样,你就不需要写一个if子句来告诉你要下降到哪个枚举变体,并且你可以选择多个枚举变体来返回Ok

enum Fruit {
    Apple(i32),
    Orange(i16),
    Rotten,
}

impl IntoResult<i32, ()> for Fruit {
    fn into_result(self) -> Result<i32, ()> {
        match self {
            Fruit::Apple(i) => Ok(i),
            Fruit::Orange(i) => Ok(i as i32),
            Fruit::Rotten => Err(()),
        }
    }
}

assert_eq!(9, inner!(Fruit::Apple(9)));

许可证

Apache2.0/MIT

无运行时依赖