有没有我可以用来期待枚举变体并提取其数据的宏?

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)),
        }
    };
}

Playground

正如评论中对 的回答所建议的那样,您可能希望将价值提取与恐慌分离开来。在那种情况下,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();
}