🦀 Tip of the day 01: Macros Aren’t As Bad As Other Languages Make Them To Be!
If you are coming from other languages, you were probably taught that macros are a dangerous “code smell.” In Rust, they are a celebrated, incredibly safe feature!
Why they aren’t a code smell in Rust:
No “Copy-Paste” Bugs: C&C++ macros (#define) do dumb text substitution before compilation, easily breaking math logic. Rust macros operate on the Abstract Syntax Tree (AST). They understand the actual structural boundaries of your code and output safe, compiler-checked expressions.
Hygienic Scoping: Variables created inside a Rust macro cannot accidentally leak out and overwrite variables in your main code.
What we actually use them for:
Variable Arguments (Variadics): Regular Rust functions require a strict, fixed number of arguments. Macros bypass this, letting you pass in as many items as you want (which is why println!(“{} {}”, a, b) and vec![1, 2, 3] are macros!).
Banishing Boilerplate: Attribute macros like #[derive(Debug, Clone)] automatically write hundreds of lines of repetitive implementation code for your structs behind the scenes.
Domain-Specific Languages (DSLs): They allow you to safely bend Rust’s syntax rules. For example, some web frameworks use macros to let you write raw HTML directly inside your Rust file: html! { <div>Hello</div> }.
The takeaway: In some languages, macros are a brittle hack to bypass the compiler. In Rust, macros are a safe, compiler-aware tool designed to write code that writes code.
🔇 Don’t ask me why a hyper-modern language forces you to use advanced meta-programming to print a simple println!(“Hello, World!”); and still hasn’t figured out native variadic functions yet. We don’t talk about that!