([ $( $elem:expr ),* ]) => // 0 or more [aa, bb, cc]
([ $( $elem:expr )* ]) => // 0 or more [aa bb cc]
([ $( $elem:expr ),+ ]) => // 1 or more [aa, bb, cc]
outer bracket → pattern $ ( $elem:expr )*
expr
→ Expression
stmt
→ Statement
ty
→ type
tt
→ token tree
ident
→ identifier
JSON macro
This token tree pattern matches to first token tree, otherwise [10,20] is read as expression and looks for From[10,20] which is wrong
([ $( $elem:tt ),* ])
macro_rules! json {
(null) => {Json::Null};
([ $( $elem:tt ),* ]) => {
Json::Array(vec![ $( json!($elem) ),* ])
};
// $value:expr, $value:tt (token tree works only)
({ $($key:tt : $value:expr),* }) => {
{
let mut fields = Box::new(HashMap::new());
$( fields.insert($key.to_string(), json!($value)); )*
Json::Object(fields)
}
};
($other:tt) => {
Json::from($other)
};
}
For example,
59 | Json::from($other)
| ^^^^^^^^^^ the trait `From<[{float}; 2]>` is not implemented for `Json`
...
74 | let role = json!({
| ________________-
75 | | "name": "movies",
76 | | "actor": [10.0, 20.0]
77 | | });
| |______- in this macro invocationr
This [10.0, 20.0]
looks for From[{float}; 2
because it is trying to evaluate that expression. Instead use $value:tt
instead. This converts to Json::Array(<[_]>::into_vec(box [Json::from(10.0), Json::from(20.0)])),
This token tree pattern matches to first token tree, otherwise [10,20] is read as expression and looks for From[10,20] which is wrong ([ $( $elem:tt ),* ])
Internal rules pattern. This is extremely useful pattern
#[macro_export]
macro_rules! foo {
(@as_expr $e:expr) => {$e};
($($tts:tt)*) => {
foo!(@as_expr $($tts)*)
};
}
/*
macro_rules! macro1 {
() => { macro!(@macro2); } ;
(@macro2) => { }
}
}
*/
fn main() {
foo!({
println!("hello") ;
});
}
TT munchers
macro_rules! handle_operations {
(up $($tt:tt)*) => {
println!("up");
handle_operations!($($tt)*);
};
(down $($tt:tt)*) => {
println!("down");
handle_operations!($($tt)*);
};
() => {};
}
fn main() {
handle_operations!(up up down down);
}
Counting macro
macro_rules! count {
() => (0usize);
( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
}
Top comments (0)