Metaprogramming treats code as data: it manipulates existing code, generates additional code, or adds capabilities. In Rust, macros perform this work at compile time and expand into ordinary structs, functions, and other code before linting, type checking, and compilation. section 1.2
Rust makes metaprogramming a practical everyday technique. A small program can use derive and test attributes, format!, dbg!, assert_eq!, and serialization macros, often hiding substantial generated code behind concise syntax. section 1.1 section 1.3
Choose metaprogramming when ordinary Rust tools are insufficient or when generated code removes meaningful repetition:
- Use declarative macros first for compact domain-specific generation based on matchers and transcribers. section 1.6 section 3.0
- Use procedural macros for lower-level token processing, including derive, attribute, and function-like macros. section 1.6 section 3.0
- Prefer functions and other normal coding tools when they solve the problem; reserve macros for difficult tasks, boilerplate, duplication, or improved application usability. section 1.6 section 1.0
One Rust program, many macro expansions
A Request struct derives Deserialize, format! builds a full name, dbg! prints it, #[test] marks a test, and assert_eq! checks expectations. These concise forms demonstrate how macros surround routine Rust development. section 1.1
Listing 1.1 The program you just wrote
use serde::Deserialize;
#[derive(Deserialize)] #1
struct Request {
given_name: String,
last_name: String,
}
fn full_name(given: &str, last: &str) -> String {
format!("{} {}", given, last) #2
}
fn main() {
let r = Request {
given_name: "Sam".to_string(),
last_name: "Hall".to_string()
};
dbg!(full_name(&r.given_name, &r.last_name));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deserialize() {
let actual: Request =
serde_json::from_str("{ \"given_name\\": \\"Test\\",
\"last_name\\": \\"McTest\\" }")
.expect("deserialize to work");
assert_eq!(actual.given_name, "Test".to_string());
assert_eq!(actual.last_name, "McTest".to_string());
}
}
Inspect the complete Rust example showing serialization, a normal function beside macros, debugging, and a deserialization test. section 1.1


