Callbacks
Due to the order that macros are expanded in, it is (as of Rust 1.2) impossible to pass information to a macro from the expansion of another macro:
macro_rules! recognize_tree { (larch) => { println!("#1, the Larch.") }; (redwood) => { println!("#2, the Mighty Redwood.") }; (fir) => { println!("#3, the Fir.") }; (chestnut) => { println!("#4, the Horse Chestnut.") }; (pine) => { println!("#5, the Scots Pine.") }; ($($other:tt)*) => { println!("I don't know; some kind of birch maybe?") }; } macro_rules! expand_to_larch { () => { larch }; } fn main() { recognize_tree!(expand_to_larch!()); // first expands to: recognize_tree! { expand_to_larch ! ( ) } // and then: println! { "I don't know; some kind of birch maybe?" } }
This can make modularizing macros very difficult.
An alternative is to use recursion and pass a callback:
// ... macro_rules! recognize_tree { (larch) => { println!("#1, the Larch.") }; (redwood) => { println!("#2, the Mighty Redwood.") }; (fir) => { println!("#3, the Fir.") }; (chestnut) => { println!("#4, the Horse Chestnut.") }; (pine) => { println!("#5, the Scots Pine.") }; ($($other:tt)*) => { println!("I don't know; some kind of birch maybe?") }; } macro_rules! call_with_larch { ($callback:ident) => { $callback!(larch) }; } fn main() { call_with_larch!(recognize_tree); // first expands to: call_with_larch! { recognize_tree } // then: recognize_tree! { larch } // and finally: println! { "#1, the Larch." } }
Using a tt
repetition, one can also forward arbitrary arguments to a callback.
macro_rules! callback { ($callback:ident( $($args:tt)* )) => { $callback!( $($args)* ) }; } fn main() { callback!(callback(println("Yes, this *was* unnecessary."))); }
You can, of course, insert additional tokens in the arguments as needed.