Подберите подчеркивание вместо идент в макросе
Я создаю макрос, который соответствует двум выражениям и идентификатору. Я хотел бы иметь возможность игнорировать идентификатор, если он не нужен, но компилятор, кажется, жалуется, если я использую _
там.
Мой макрос:
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_some!(obtain_an_option(), _, do_something())
Второй вызов не проходит.
Я обошел это, определив второй макрос if_some_!
это не получает идентификатор (я не мог использовать второй образец также). Я уверен, что есть способ сказать "здесь принять идентификатор или просто _
,
Может быть, уже есть макрос / функция для этого (например, Option::map
сейчас думаю об этом)... тем не менее было бы неплохо сейчас.
2 ответа
Option::map
кажется, лучшее решение для этой конкретной проблемы, но когда вам действительно нужен макрос, который ожидает и ident, и _
в качестве шаблона, вы также можете использовать $p:pat
фрагмент. Фрагмент, конечно, принимает более широкий спектр шаблонов, таких как (ref 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)
}
Самый простой способ - добавить вторую руку, которая соответствует подчеркиванию:
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
,