はじめに
こんにちは。細々とプログラミングをしているsotanengelです。
この記事は以下の記事の連載です。
他の連載記事 (詳細)
- Day 1:型システムを使ってデータ構造を再現しよう
- Day 2:型システムを用いて共通の挙動を表現しよう
- Day 3:OptionとResultに対してはmatchを用いずに変換しよう
- Day 4:標準のErrorを使おう
- Day 5:型変換を理解しよう
- Day 6:newtypeパターンを活用しよう
- Day 7:複雑な型にはビルダを使おう
- Day 8:明示的なループの代わりにイテレータ変換を使用することを検討しよう
- Day 9:標準トレイトに習熟しよう
- Day 10:RIIパターンにはDropトレイトを実装しよう
- Day 11:ジェネリクスとトレイトオブジェクトのトレードオフを理解しよう
- Day 12:デフォルト実装を用いて、実装しなければならないトレイトメソッドを最小限にしよう
- Day 13:Don't panic
- Day 14:リフレクションを避けよう
- Day 15:可視範囲を最小化しよう
- Day 16:ワイルドカードインポートを避けよう
- Day 17:パブリックインターフェースのドキュメントを書こう
- Day 18:分別を持ってマクロを使おう
- Day 19:Clippyに耳を傾けよう
- Day 20:ユニットテスト以上のものを書こう
また本記事はEffective Rust(David Drysdale (著), 中田 秀基 (翻訳))を参考に作成されております。とてもいい書籍ですので興味を持った方は、ぜひ読んでみてください!
今日の内容
概要
Rustでもメタプログラミングをマクロを使うことで実現することができます。
特に以下の状況の時にマクロを使うことが推奨されます。
- 同じコードを繰り返し書いているとき→マクロ
- 複数の型に同じコードを書いているとき→トレイト制約を持つジェネリクス
- 特定の型の複数の値に対して全く同じ処理を書いているとき→共有関数
例文を解くことでマクロの使い方や注意点を確認しましょう。
マクロの定義の順番は気をつけよう
問(リンク)
マクロを定義する場合には順番に気をつける必要があります。
コード (詳細)
fn main() {
// マクロを呼び出す
print_hello!();
}
// TODO: 宣言的マクロの定義の位置は配慮する必要があります。
// 適切な場所に配置し直してください。
macro_rules! print_hello {
() => {
println!("Hello, world!");
};
}
解答(リンク)
コード参照。
コード (詳細)
// 宣言的マクロを定義する
macro_rules! print_hello {
() => {
println!("Hello, world!");
};
}
fn main() {
// マクロを呼び出す
print_hello!();
}
マクロの中で使う変数を適切に定義しよう
問(リンク)
マクロ内部で使用するローカル変数を定義する方法を確認しましょう。
コード (詳細)
解答(リンク)
コード参照。
コード (詳細)
// 宣言的マクロを定義する
macro_rules! print_value {
($x:expr) => {
println!("The value is: {}", $x);
};
}
fn main() {
let x = 42;
// マクロを呼び出す
print_value!(x);
}
さいごに
もしも本リポジトリで不備などあれば、リポジトリのissueやPRなどでご指摘いただければと思います。