有没有我可以用来期待枚举变体并提取其数据的宏?
Is there a macro I can use to expect a variant of an enum and extract its data?
给定一个像
这样的枚举
struct Earth { water: usize }
struct Mars { redness: usize }
enum World {
Mars(Mars),
Earth(Earth),
}
我写的一个常见模式是
fn something_expecting_mars(planet: World) {
let mars = match planet {
World::Mars(data) => data,
_ => panic!("Shouldn't be here now"),
}
}
是否有宏可用于预期枚举的变体并随后提取其数据?
// rewriting to this
let mars = expect_v!(planet, World::Mars);
只使用 if let
而不是 match
有什么问题吗?
mars = if let World::Mars(data) = planet { data } else { panic!("Woot woot")}
标准库为 testing a match 提供了宏,但没有提供用于提取值的宏。但是,编写一个相当容易:
macro_rules! expect_v {
($e:expr, $p:path) => {
match $e {
$p(value) => value,
_ => panic!("expected {}", stringify!($p)),
}
};
}
正如评论中对 的回答所建议的那样,您可能希望将价值提取与恐慌分离开来。在那种情况下,return 一个 Option
代替,如果他们希望调用 unwrap()
:
让调用者恐慌
macro_rules! extract {
($e:expr, $p:path) => {
match $e {
$p(value) => Some(value),
_ => None,
}
};
}
// ...
fn something_expecting_mars(planet: World) {
let mars = extract!(planet, World::Mars).unwrap();
}
给定一个像
这样的枚举struct Earth { water: usize }
struct Mars { redness: usize }
enum World {
Mars(Mars),
Earth(Earth),
}
我写的一个常见模式是
fn something_expecting_mars(planet: World) {
let mars = match planet {
World::Mars(data) => data,
_ => panic!("Shouldn't be here now"),
}
}
是否有宏可用于预期枚举的变体并随后提取其数据?
// rewriting to this
let mars = expect_v!(planet, World::Mars);
只使用 if let
而不是 match
有什么问题吗?
mars = if let World::Mars(data) = planet { data } else { panic!("Woot woot")}
标准库为 testing a match 提供了宏,但没有提供用于提取值的宏。但是,编写一个相当容易:
macro_rules! expect_v {
($e:expr, $p:path) => {
match $e {
$p(value) => value,
_ => panic!("expected {}", stringify!($p)),
}
};
}
正如评论中对 Option
代替,如果他们希望调用 unwrap()
:
macro_rules! extract {
($e:expr, $p:path) => {
match $e {
$p(value) => Some(value),
_ => None,
}
};
}
// ...
fn something_expecting_mars(planet: World) {
let mars = extract!(planet, World::Mars).unwrap();
}