Hello people!
tldr: How can I unify these two macros, adding one more parameter? The only difference is the &self
in one and the &mut self
in the other.
macro_rules! get_function_nomut {
( $name:ident, $ref_function:ident, $return_type:ty ) => {
pub fn $name (&self) -> $return_type {
$ref_function!(self.data)
}
}
}
macro_rules! get_function_mut {
( $name:ident, $ref_function:ident, $return_type:ty ) => {
pub fn $name (&mut self) -> $return_type {
$ref_function!(self.data)
}
}
}
Can macros have boolean parameters on which I can check to generate either &self
or &mut self
in the code?
The above code with some context to make it run can be found here: Rust Playground
Why: The code above is of course simplified. In the actual usage scenario, there is quite some code duplication to avoid. This thread is a follow-up to [SOLVED] Avoid duplication for &mut vs & access
1 Like
One option might be:
macro_rules! get_function {
($name:ident, $ref_function:ident, $return_type:ty, $typ:ty) => {
pub fn $name (self: $typ) -> $return_type {
$ref_function!(self.data)
}
};
}
get_function!(get_ref, ref_function_nomut, &i32, &Self);
get_function!(get_ref_mut, ref_function_mut, &mut i32, &mut Self);
So the user of the macro specifies the type of self as the last macro arg.
Another option might be to do something like:
macro_rules! get_function {
($name:ident, $ref_function:ident, $return_type:ty, immut) => {
pub fn $name (&self) -> $return_type {
$ref_function!(self.data)
}
};
($name:ident, $ref_function:ident, $return_type:ty, mut) => {
pub fn $name (&mut self) -> $return_type {
$ref_function!(self.data)
}
};
}
get_function!(get_ref, ref_function_nomut, &i32, immut);
get_function!(get_ref_mut, ref_function_mut, &mut i32, mut);
Here you have 2 rules that expect either the token "immut" or "mut" - anything else will barf at macro expansion time.
There're likely better/more elegant ways - my macro-fu isn't all that strong
.
2 Likes
Thank you very much, the first method works!
(The second one would lead to the same code duplication as not using macros at all, so I haven't tried it.)