マクロ

マクロ

上級

説明

マクロはRustプログラマーの道具箱の中でも強力な機能です。そしてマクロ・バイ・イグザンプルは、その力を比較的シンプルに使えるようにしてくれる仕組みです。さっそくひとつ書いてみましょう!

背景

マクロとは何でしょうか? Wikipediaでは次のように説明されています。

コンピューターサイエンスにおけるマクロ(「macroinstruction」の略で、ギリシャ語のμακρός「長い」に由来します)とは、ある入力列(多くの場合、文字の並び)を、定められた手順にしたがって、置き換え用の出力列(同じく多くの場合、文字の並び)に対応付ける規則、またはパターンのことです。マクロの使用を特定の並びに具体化(変換)するこの対応付けの処理は、マクロ展開として知られています。

なるほど、よくわかります。ただ、もっと具体的に言えば、マクロとはコンパイル時にコードを生成できる特別な構文のことです。マクロはコンパイル時の計算にも使えますが、それよりも、コードを抽象化するもうひとつの手段として使われることのほうが多いでしょう。たとえば、println!()やvec![]はすでに使ったことがあるはずです。これらはどちらも任意の数の引数を取るため、単純な関数として表すことはできません。一方で、展開されれば必ず、ごく標準的なRustのコードになります。興味があれば、cargo expandサブコマンドを使うと、自分のコードでマクロが展開された結果を確認できます。

Rustのマクロについてもっと知りたい場合は、The Rust Bookに詳しく解説した章があります。

問題

vec![]マクロを使えば、任意の長さのVecをその場で作れます。しかしRustには、HashMapをその場で作る方法が標準では用意されていません。そこで、hashmap!()マクロを書いてこの問題を解決しましょう。

たとえば、ライブラリの利用者はhashmap!('a' => 3, 'b' => 11, 'z' => 32)のように書くかもしれません。これは次のコードに展開されるべきです。

{
   let mut hm = HashMap::new();
   hm.insert('a', 3);
   hm.insert('b', 11);
   hm.insert('z', 32);
   hm
}

なお、maplitクレートには、この演習を完璧に解いてくれるマクロが用意されています。このクレートは使わず、自分自身の解答を実装してください。また、そのソースを読む前に、まずは自分で挑戦してみてください。


出典

Peter Goodspeed-Niklaus
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
Rust Exercism

マクロを始める準備はできましたか?

Exercismに登録すれば、99個の演習、そして本物の人間によるメンタリングとともに、Rustを学んでマスターできます。すべて無料です。