У меня есть структура с двумя необязательными полями, и я хотел бы предоставить специальный макрос для упрощения создания экземпляров.
Макрос должен принимать один обязательный аргумент и три необязательных аргумента. Последний необязательный аргумент должен принимать список значений. И я хотел бы использовать для этого ровно одну скороговорку.
Наконец-то я это сделал и все отлично работает:
#[derive(Debug)]
pub enum Variant {
OptionOne,
OptionTwo,
}
#[derive(Debug)]
pub struct TheStruct{
string: String,
first: Option<Variant>,
second: Option<Variant>,
numbers: Vec<u32>,
}
impl TheStruct {
// doesn't matter
}
#[doc(hidden)]
#[macro_export]
macro_rules! the_macro_int {
($the_struct:ident, numbers, { $($w:expr),*$(,)*}) => {
$($the_struct.numbers.push($w);)*
};
($the_struct:ident, first, {$w:expr}) => {
$the_struct.first = Some($w);
};
($the_struct:ident, second, {$w:expr}) => {
$the_struct.second = Some($w);
};
}
#[macro_export]
macro_rules! the_macro {
(string: $string:expr, $($kind:ident : $val:tt),*$(,)*) => {{
let mut the_struct = $crate::TheStruct{
string: $string,
first: None,
second: None,
numbers: std::vec::Vec::new(),
};
$($crate::the_macro_int!(the_struct, $kind, $val);)*
the_struct
}};
}
fn main() {
let the_struct = the_macro!(
string: "Hello".to_owned(),
first: { Variant::OptionOne },
numbers: (1, 3, 4),
);
println!("the_struct:{:?}", the_struct);
}
Детская площадка
одна вещь делает меня несчастным: скобки в first: { Variant::OptionOne },
.
Я пытался заменить свой шаблон на (string: $string:expr, $($kind:ident : $val:expr),*$(,)*)
, но он больше не работает для numebrs
.
Возможно ли это переопределить шаблон для the_macro
, чтобы first: Variant::OptionOne,
был действительным, а numbers
все еще может принимать список элементов? Вид скобок для numbers
не имеет значения, но я не могу заменить список вещей только Ve c или чем-то подобным.
PS Я не ищу решение с несколькими шаблонами.