That's both genius and terrifying.
It doesn't seem to work when you swap the argument order, though:
error[E0308]: mismatched types
--> src/main.rs:21:12
|
21 | ($(Arg::<_, {encode(stringify!($arg))}>($t)),*)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `125762622027123_u64`, found `418464099429_u64`
...
30 | let (x, y) = from_polar(args!{angle = 0.0, radius = 1.0});
| -------------------------------- in this macro invocation
|
= note: expected struct `Arg<f64, 125762622027123_u64>`
found struct `Arg<{float}, 418464099429_u64>`
= note: this error originates in the macro `args` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> src/main.rs:21:12
|
21 | ($(Arg::<_, {encode(stringify!($arg))}>($t)),*)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `418464099429_u64`, found `125762622027123_u64`
...
30 | let (x, y) = from_polar(args!{angle = 0.0, radius = 1.0});
| -------------------------------- in this macro invocation
|
= note: expected struct `Arg<f64, 418464099429_u64>`
found struct `Arg<{float}, 125762622027123_u64>`
= note: this error originates in the macro `args` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0308`.
error: could not compile `playground` due to 2 previous errors
I made an alternate version which abuses the fact that items (e.g. functions and structs) live in a different namespace to modules to create a hidden Args
struct that gets passed to the function. My version won't work for references, though.
macro_rules! args {
(fn $id:ident ($($arg:ident: $t:ty),*) $($tail:tt)*) => {
fn $id($id::Args { $($arg),* }: $id::Args) $($tail)*
#[doc(hidden)]
pub mod $id {
pub struct Args {
$(pub $arg : $t),*
}
}
};
($id:ident($($arg:ident = $t:expr),*)) => {
$id($id::Args { $($arg: $t),* })
};
}
args! {
fn from_polar(radius: f64, angle: f64) -> (f64, f64) {
(radius*angle.cos(), radius*angle.sin())
}
}
fn main() {
let (x, y) = args!(from_polar(angle = 0.0, radius = 1.0));
println!("({}, {})", x, y);
}
(playground)