2 个版本
使用旧的 Rust 2015
0.1.2 | 2023 年 3 月 9 日 |
---|---|
0.1.0 | 2023 年 3 月 9 日 |
#997 in Rust 模式
15KB
219 行
The inner!
宏使深入到枚举变体变得更加方便。The some!
和 ok!
宏将枚举转换为 Option
或 Result
。
有用的 unwrap
最简单的情况几乎像 unwrap
let x = Some(1);
let y: Result<_, ()> = Ok(2);
assert_eq!(inner!(x), 1);
assert_eq!(inner!(y), 2);
...但如果你在 None
或 Err
值上使用它
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 子句计算默认值,或使用流程控制(例如 break
、continue
或 return
)。
想访问 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
。
它与您的枚举也一起工作
它不仅与 Option
和 Result
一起工作。只需添加一个 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
子句则提供了最大的灵活性,允许返回Err
或Ok
。
另一个选项是为你的枚举实现这个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