関数的マクロ
Effective Rust ― Rustコードを改善し、エコシステムを最大限に活用するための35項目
名前の通り関数のように呼び出すことができる マクロ
引数を 1 つ だけ持つ
そのため、以下のように複数の引数を渡しても、内部的には 1 つの引数として扱われる
my_func_macro!(15, x + y, f32::consts::PI);
引数の トークン 列にアクセスでき、戻り値は任意のトークンを返す
下記のサンプルから分かるように、引数で渡ってくる値は 低レベル なので、実装時には自身でパースする必要がある
e.g.
複数の引数が渡ってくる場合は、カンマ区切りの値を分割するために TokenTree::Punct を探す必要がある
syn クレートを用いると、このパースが楽になる
そのため、関数的マクロを用いるよりも 宣言的マクロ を用いた方が簡単である
一方、通常の Rust コードとしてはパースできないような入力値を受け取る柔軟性を持つ
e.g.
code:rs
use proc_macro::TokenStream;
#proc_macro
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) }
#Rust #手続き的マクロ