When to Use a Macro vs a Function vs a Trait in Rust

Use functions for logic, traits for shared behavior, and macros for code generation or variable arguments.

Use a function for standard logic, a trait to define shared behavior across types, and a macro only when you need to generate code or accept variable arguments that functions cannot handle.

// Function: Standard logic with fixed arguments
fn add(a: i32, b: i32) -> i32 { a + b }

// Trait: Shared behavior for different types
trait Printable {
    fn print(&self);
}

// Macro: Code generation or variable arguments
macro_rules! vec_of {
    ($elem:expr; $n:expr) => {
        vec![$elem; $n]
    };
}