Using an optional argument inside a rust macro $(...)?
I'd like to be able to change how a struct is formulated. For example:
struct Field<T>(T);
struct OptionalField<T>(T);
define_struct!(StructName => {
field_one: i32,
field_two?: i32
});
// would ideally evaluate to
struct StructName {
field_one: Field<i32>,
field_two: OptionalField<i32>
}
Writing a macro with repeated sections isn't the difficult part however, the part that's giving me trouble is how I can make the optional question mark change the type used as the struct's field type. So far I've tried this:
macro_rules! define_struct {
($name:ident => {
$($field_name:ident$(?)?: $type:ty),*
}) => {
struct $name {
$($field_name: $(Optional)?Field<$type>),*
}
};
}
The macro invocation is fine and follows the defined pattern however inserting the Optional
before the Field
identifier is what's proving difficult. The section $(Optional)?
throws the error:
attempted to repeat an expression containing no syntax variables matched as repeating at this depth
|
| $($field_name: $(Optional)?Field<$type>),*
| ^^^^^^^^^^
Is there any way to insert a keyword depending upon the presence of an optional macro pattern without having to use a syntax variable?
You can do it with an incremental tt
muncher and push-down accumulation :
macro_rules! define_struct {
(@fields $name:ident { $($fields:tt)* } $field_name:ident?: $type:ty, $($rest:tt)*) => {
define_struct!(@fields
$name {
$($fields)*
$field_name: OptionalField<$type>,
}
$($rest)*);
};
(@fields $name:ident { $($fields:tt)* } $field_name:ident: $type:ty, $($rest:tt)*) => {
define_struct!(@fields
$name {
$($fields)*
$field_name: Field<$type>,
}
$($rest)*);
};
(@fields $name:ident { $($fields:tt)* }) => {
struct $name { $($fields)* }
};
($name:ident => { $($fields:tt)* }) => {
define_struct!(@fields $name {} $($fields)*);
};
}
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.