Procedural macros
Declarative macros can become tedious to read and maintain when your code generation logic becomes complex, as you need to write your logic with its own DSL to manipulate tokens. There are better, more flexible ways than using macro_rules!
. For complex problems, you can leverage procedural macros as they are better suited to writing something non-trivial. They are suitable for cases where you need full control of code generation.
These macros are implemented as functions. These functions receive the macro input as a TokenStream
type and return the generated code as a TokenStream
after undergoing any transformation at compile time. To mark a function as a procedural macro, we need to annotate it with the #[proc_macro]
attribute. At the time of writing this book, procedural macros come in three forms, which are categorized by how they are invoked:
- Function-like procedural macros: These use
#[proc_macro]
attribute on functions. Thelazy_static!
macro from thelazy_static
crate...