問題一覧に戻る
上級マクロ
問題107: 宣言的マクロ応用

宣言的マクロの高度な技法として、再帰的パターンマッチングと可変長引数処理があります。マクロは自分自身を呼び出して再帰的に展開でき、リストや繰り返し構造を処理できます。$()+や$()*の繰り返しパターンで任意数の引数を受け取り、ttマンチャー(トークンツリー操作)で複雑な構文変換を実現。コンパイル時に全て展開されるため実行時オーバーヘッドなし。標準ライブラリのvec!マクロなどがこれらの技法を活用しています。

// 再帰的マクロ
macro_rules! count_args {
() => { 0 };
( $head:expr ) => { 1 };
( $head:expr, $($tail:expr),* ) => {
1 + count_args!($())
};
}

// 可変長引数マクロ
macro_rules! min {
( $x:expr ) => { $x };
( $x:expr, $($y:expr),+ ) => {{
let min = !($($y),+);
if $x < min { } else { min }
}};
}

// トークンツリー操作
macro_rules! replace_expr {
($_t:tt $sub:expr) => { $sub };
}

macro_rules! tuple_from_list {
( $($x:expr),* ) => {
( $( replace_expr!($x ) ),* )
};
}

fn main() {
println!("count: {}", count_args!(1, 2, 3));
println!("min: {}", min!(5, 2, 8, 1));

let t = tuple_from_list!(a, b, c);
println!("{:?}", t);
}