Macros 在宏中匹配下划线而不是标识符

Macros 在宏中匹配下划线而不是标识符,macros,rust,rust-macros,Macros,Rust,Rust Macros,我正在创建一个宏,它匹配两个表达式和一个标识符。如果不需要标识符,我希望能够忽略它,但是如果我在那里使用,,编译器似乎会抱怨 我的宏: macro_rules! if_some { ($x:expr, $id:ident, $expr:expr) => { match $x { None => None, Some($id) => Some($expr), } }; } 我想做的是

我正在创建一个宏,它匹配两个表达式和一个标识符。如果不需要标识符,我希望能够忽略它,但是如果我在那里使用
,编译器似乎会抱怨

我的宏:

macro_rules! if_some {
    ($x:expr, $id:ident, $expr:expr) => {
        match $x {
            None => None,
            Some($id) => Some($expr),
        }
    };
}
我想做的是:

if_some!(obtain_an_option(), x, do_something_with(x))

第二次呼叫失败

我通过定义第二个宏
if\u some\uu没有收到标识符(我也不能使用第二种模式)。我相信有一种方式可以说“在这里接受一个标识符,或者只接受


也许已经有了一个宏/函数(比如我现在想的是
Option::map
)。不过现在最好是这样。

最简单的方法是添加第二个与下划线匹配的手臂:

macro_rules! if_some {
    ($x:expr, _, $expr:expr) => {
        match $x {
            None => None,
            Some(_) => Some($expr),
        }
    };

    ($x:expr, $id:ident, $expr:expr) => {
        match $x {
            None => None,
            Some($id) => Some($expr),
        }
    };
}

而且,是的,这听起来像是您只需要
选项::map

最简单的方法是添加与下划线匹配的第二个臂:

macro_rules! if_some {
    ($x:expr, _, $expr:expr) => {
        match $x {
            None => None,
            Some(_) => Some($expr),
        }
    };

    ($x:expr, $id:ident, $expr:expr) => {
        match $x {
            None => None,
            Some($id) => Some($expr),
        }
    };
}

是的,这听起来像是你想要
Option::map

Option::map
似乎是解决这个特殊问题的最佳方案,但是当你真的需要一个宏,它需要同时使用ident和
\
作为模式时,你也可以使用
$p:pat
片段。当然,这个片段接受的范围更广例如
(参考x,y)
,但通常这是可以接受的

macro_rules! if_some {
    ($x:expr, $p:pat, $expr:expr) => {
        match $x {
            None => None,
            Some($p) => Some($expr),
        }
    };
}

fn main() {
    println!("{:?}", if_some!(Some(12), x, x + 1)); // Some(13)
    println!("{:?}", if_some!(Some(12), _, 1)); // Some(1)
}

选项::map
似乎是解决此特定问题的最佳解决方案,但当您确实需要一个同时使用ident和
\uuu
作为模式的宏时,您也可以使用
$p:pat
片段。当然,该片段可以接受范围更广的模式,如
(参考x,y)
,但这通常是可以接受的

macro_rules! if_some {
    ($x:expr, $p:pat, $expr:expr) => {
        match $x {
            None => None,
            Some($p) => Some($expr),
        }
    };
}

fn main() {
    println!("{:?}", if_some!(Some(12), x, x + 1)); // Some(13)
    println!("{:?}", if_some!(Some(12), _, 1)); // Some(1)
}