TL;DR

  • マクロは可読性と保守性を下げる。マクロで作った DSL を読むには、マクロの実装まで理解する必要がある。
  • 1 行の呼び出しが大量のコードを生成するので、コードの肥大化を招きやすい。

内容

項目28 分別をもってマクロを使おうのうち、マクロのデメリットの話である。

可読性と保守性の低下

マクロを使うと DSL を作れる。しかし、コードを読んで保守する人は、Rust だけでなく、その DSL もマクロの実装を含めて理解しなければならない。たとえばマクロを使うべきケースの http_codes! は Status という enum を作るが、DSL を見てもそれは分からない。

また、マクロの中のコードは Rust の構文の慣習に従わないので、rustfmt で整形されない。

macro_rules! square {
    { $e:expr } => {
        {
            let x = $e;
            x*x // x * x と整形されない
        }
    }
}

http_codes! では、Informational などの Group のバリアントを、接頭辞の Group:: も use もなしに使っている。これも通常の Rust のコードとは見た目が違う。

コンパイラのエラーメッセージも、どのマクロがどのマクロを呼び出し、どこで問題が起きたのかを、必ずしも詳しく追ってくれない。このときは cargo-expand で展開後のコードを見ると役に立つ。

コードの肥大化

1 行のマクロ呼び出しが、数百行のコードを生成することもある。しかし、呼び出し側からはそれが分からない。そのため、呼び出しが不要になっても削除されずに残り続けやすい。

キーワード