関数的マクロ
名前の通り関数のように呼び出すことができる マクロ 引数を 1 つ だけ持つ
そのため、以下のように複数の引数を渡しても、内部的には 1 つの引数として扱われる
my_func_macro!(15, x + y, f32::consts::PI);
引数の トークン 列にアクセスでき、戻り値は任意のトークンを返す 下記のサンプルから分かるように、引数で渡ってくる値は 低レベル なので、実装時には自身でパースする必要がある e.g.
複数の引数が渡ってくる場合は、カンマ区切りの値を分割するために TokenTree::Punct を探す必要がある
そのため、関数的マクロを用いるよりも 宣言的マクロ を用いた方が簡単である 一方、通常の Rust コードとしてはパースできないような入力値を受け取る柔軟性を持つ
e.g.
code:rs
use proc_macro::TokenStream;
pub fn my_func_macro(args: TokenStream) -> TokenStream {
println!("Input Token Stream is:");
for tt in args {
println!(" {tt:?}");
}
TokenStream::new()
}
実行結果
code:_
Input Token Stream is:
Literal { kind: Integer, symbol: "15", suffix: None, span: #0 bytes(90..92) } Punct { ch: ',', spacing: Alone, span: #0 bytes(92..93) } Ident { ident: "x", span: #0 bytes(94..95) } Punct { ch: '+', spacing: Alone, span: #0 bytes(96..97) } Ident { ident: "y", span: #0 bytes(98..99) } Punct { ch: ',', spacing: Alone, span: #0 bytes(99..100) } Ident { ident: "f32", span: #0 bytes(101..104) } Punct { ch: ':', spacing: Joint, span: #0 bytes(104..105) } Punct { ch: ':', spacing: Alone, span: #0 bytes(105..106) } Ident { ident: "consts", span: #0 bytes(106..112) } Punct { ch: ':', spacing: Joint, span: #0 bytes(112..113) } Punct { ch: ':', spacing: Alone, span: #0 bytes(113..114) } Ident { ident: "PI", span: #0 bytes(114..116) }