首页 > 解决方案 > 宏匹配臂模式“没有规则需要令牌`if`”

问题描述

Box<dyn error::Error>所以我有这个用于匹配多种错误类型的宏

#[macro_export]
macro_rules! dynmatch {
    ($e:expr, $(type $ty:ty {$(arm $pat:pat => $result:expr),*, _ => $any:expr}),*, _ => $end:expr) => (
        $(
            if let Some(e) = $e.downcast_ref::<$ty>() {
                match e {
                    $(
                        $pat => {$result}
                    )*
                    _ => $any
                }
            } else
        )*
        {$end}
    );
}

在我尝试添加匹配围裙之前,它工作正常。当我尝试在模式中使用“if”语句时,它给了我错误no rules expected the token 'if'

let _i = match example(2) {
    Ok(i) => i,
    Err(e) => {
        dynmatch!(e,                                                            
            type ExampleError1 {                                                
                arm ExampleError1::ThisError(2) => panic!("it was 2!"),  
                _ => panic!("{}",e)                                             
            },
            type ExampleError2 {
                arm ExampleError2::ThatError(8) => panic!("it was 8!"),
                arm ExampleError2::ThatError(9..=11) => 10,
                _ => panic!("{}",e)
            }, 
            type std::io::Error {                                               
                arm i if i.kind() == std::io::ErrorKind::NotFound => panic!("not found"), //ERROR no rules expected the token `if`
                _ => panic!("{}", e)
            },
            _ => panic!("{}",e)                                                 
        )
    }
};

有没有办法在我的模式匹配中使用匹配保护而不会出现令牌错误?

标签: error-handlingrustmacrospattern-matching

解决方案


当然,即使我花了大约一个小时寻找解决方案,但在我发布这个问题之后,我找到了答案。

正确的宏如下所示:

#[macro_export]
macro_rules! dynmatch {
    ($e:expr, $(type $ty:ty {$(arm $( $pattern:pat )|+ $( if $guard: expr )? => $result:expr),*, _ => $any:expr}),*, _ => $end:expr) => (
        $(
            if let Some(e) = $e.downcast_ref::<$ty>() {
                match e {
                    $(
                        $( $pattern )|+ $( if $guard )? => {$result}
                    )*
                    _ => $any
                }
            } else
        )*
        {$end}
    );
}

归功于生锈的比赛!源代码行 244-251


推荐阅读