Created
June 20, 2017 23:38
-
-
Save anonymous/95bff4309b1036ae6d4e3b4686fc262b to your computer and use it in GitHub Desktop.
Shared via Rust Playground
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// This auxiliary macro generates an ident for each argument passed to it, | |
/// and then calls another macro back with the generated idents. | |
macro_rules! gensym { | |
// base case: we send all the collected idents back to the other macro | |
(@go $callback:ident ($($args:tt)*) ($($i:ident)*)) => { | |
$callback!($($args)* $($i)*) | |
}; | |
// recursion: here, we add in a new ident named "x" (but distinct from every other "x") | |
(@go $callback:ident $args:tt ($($i:ident)*) $head:tt $($tail:tt)*) => { | |
gensym!(@go $callback $args ($($i)* x) $($tail)*) | |
// ^ notice I pass through one fewer arg ($head is gone) | |
// ^ new ident!!! | |
}; | |
// entry point: here, you pass in N tokens for $scratch, and the macro recurses that many times | |
($callback:ident!$args:tt $($scratch:tt)*) => { | |
gensym!(@go $callback $args () $($scratch)*) | |
// | | | | | | || ^----------^ at the end are the arguments telling us how many times to recurse | |
// | | | | | | ^^ in this list we'll collect generated idents | |
// | | | | ^---^ arguments to pass along to the other macro | |
// | | ^------^ the macro to call back | |
// ^-^ jump to inner macro rule | |
} | |
} | |
/// Silly macro that uses N idents to declare some variables, init them to zero, and print them | |
macro_rules! thing { | |
// this is the callback rule (gensym! calls this after generating idents) | |
(@go [$($t:ty)*] $($i:ident)*) => {{ | |
$(let $i: $t = 0;)* | |
format!("{:?}", ($($i + <$t as Default>::default()),*)) | |
}}; | |
// entry point rule | |
($($t:ty)*) => { | |
gensym!(thing!(@go [$($t)*]) $(($t))*) | |
// | | ^------^ pass along all the types, wrapped in parens just to make sure they are one tt each | |
// ^------------------^ first part tells gensym! how to call us back | |
} | |
} | |
fn main() { | |
println!("{}", thing!(u8 u32 u16)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment