简体   繁体   中英

Match an underscore instead of ident in macro

I'm creating a macro that matches two expressions and an identifier. I would like to be able to ignore the identifier if it's not needed, but the compiler seems to complain if I use _ there.

My macro:

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

What I'd like to do:

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

and

if_some!(obtain_an_option(), _, do_something())

The second call fails.

I worked around it by defining a second macro if_some_! that doesn't receive an identifier (I could not use a second pattern either). I'm sure there's a way to say "here accept an identifier or just _ .

Maybe there's already a macro/function for this (like Option::map now I think about it)... nevertheless it'd be nice to now.

The simplest way is to add a second arm that matches an underscore:

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

And, yes, this sounds like you just want Option::map .

Option::map seems to be the best solution for this particular problem, but when you really need a macro which expect both idents and _ as a pattern, you can also use the $p:pat fragment. The fragment of course accepts a broader range of patterns like (ref x, y) , but typically this will be acceptable.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM