マクロの定義側と利用側で識別子を共有する方法について。
マクロの定義側と利用側では識別子の空間が分離されている。
これにより定義側も利用側も識別子の衝突を気にせずコーディングできる。
これは衛生的 (higienic) と呼ばれる特徴である。
マクロの定義側と利用側で識別子を共有したい場合、衛生性が逆に問題となる。
例えば、マクロによるコールバックのようなパターンを考える。そこでは、マクロが定義した変数をマクロに渡したブロックが受け取り、そのブロックをマクロのコードが実行する。このような構成の場合、変数の共有は必須になる。
以下では、マクロ with_var が生成した識別子 x を、マクロに与えられたブロックから参照できないためエラーになる。
macro_rules! with_var {
($block:block) => {
let x = "hello";
$block
}
}
fn main() {
with_var!({ println!("{x}") });
}
error[E0425]: cannot find value `x` in this scope
--> src/main.rs:9:28
|
9 | with_var!({ println!("{x}") });
| ^ not found in this scope
このような場合、識別子の名前をキャプチャ ($) で導入すればよい。
以下では、マクロ with_var が生成した識別子 x を、マクロに与えられたブロックから参照できるためエラーにならない。
macro_rules! with_var {
($var:ident $block:block) => {
let $var = "hello";
$block
}
}
fn main() {
with_var!(x { println!("{x}") });
}