Reputation: 161
I've created a Rust macro which expands to a function declaration.
macro_rules! build_fn
{
($name:tt) => {
pub fn $name(&self) -> Result<i32, Box<dyn Error>>
{
// <implementation>
Ok(0)
}
};
}
Is it possible to expand this so the macro can take variable parameters?
e.g.
($name:tt, /*$variable_args ? */) => {
pub fn $name(&self, /*$variable_args ? */) -> Result<i32, Box<dyn Error>>
{
// ...
Ok(0)
}
};
}
Upvotes: 7
Views: 7778
Reputation: 715
Since @ranfdev's answer is not currently compiling, I've fixed & simpified & extended it to support multiple types -- and it now runs in Rust stable:
use std::fmt::Write;
macro_rules! build_vararg_fn {
($name:tt, $($v:tt: $t:ty),+) => {
fn $name($($v: $t),+) {
let mut msg = String::from("args: ");
$(
write!(msg, "{:?}, ", $v).unwrap();
)+
println!("{}", &msg[..msg.len()-2]);
}
}
}
fn main() {
build_vararg_fn!(test_single_arg, x: i32);
build_vararg_fn!(test_multi_arg, x: i32, y: i32);
build_vararg_fn!(test_multi_type, x: i32, y: i32, z: f64);
test_single_arg(10);
test_multi_arg(1, 2);
test_multi_type(1, 2, 3.14159);
}
Output:
args: 10
args: 1, 2
args: 1, 2, 3.14159
See it on Playgroud!
Upvotes: 7
Reputation: 73
Indeed, it's possible. You need to expand the parameters as $field: $ty
:
use std::error::Error;
macro_rules! build_fn
{
($name:tt, $($v:ident: $t:ty),*) => {
pub fn $name(&self, $($v: $t),*)
{
let args = [$($v,)*];
println!("Args = {:?}", args);
}
};
}
struct MyStruct {}
impl MyStruct {
build_fn!(test_single_arg, x: i32);
build_fn!(test_multi_arg, x: i32, y: i32);
}
fn main() -> Result<(), Box<dyn Error>> {
let my_struct = MyStruct {};
my_struct.test_single_arg(10);
my_struct.test_multi_arg(1, 2);
Ok(())
}
Link to the playground: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=d798cc6a744b53af47dd8cf40fc3b115
Upvotes: 5