5

I've found several useful macros in Rust, namely: file!(), line!(), stringify!() I've also found that Rust allows macros with variable arguments, as stated here:

macro_rules! print_all {
    ($($args:expr),*) => {{
        $(
            println!("{}", $args);
        )*
    }}
}

My goal is to somehow combine all those macros inside one which I will use during troubleshooting/debugging. So calling trace! macro on the following example:

let a: i32 = 1;
let b: i32 = 2;
trace!(a,b)

should expand to something like this:

println!("TRACE: file: {}, line: {}, a: {}, b: {}", file!(), line!(), a, b);

Is it possible? If yes, how would such a macro work?

trent
  • 25,033
  • 7
  • 51
  • 90
Wakan Tanka
  • 7,542
  • 16
  • 69
  • 122
  • 3
    Not to rain on creativity, but this looks *very* similar to the standard [`dbg!`](https://doc.rust-lang.org/std/macro.dbg.html) macro (still a valid question to ask how it'd work) – kmdreko Oct 15 '20 at 14:59
  • Is there something you don't like about the answer provided, which was not accepted? – AmigoNico Dec 12 '21 at 20:16

1 Answers1

7

You could do something like this:

macro_rules! trace {
    ($($args: expr),*) => {
        print!("TRACE: file: {}, line: {}", file!(), line!());
        $(
            print!(", {}: {}", stringify!($args), $args);
        )*
        println!(""); // to get a new line at the end
    }
}

There is likely a small overhead to calling print! multiple times, since each call will result in a system call and will also check for IO errors. However, constructing a single formatting string for arbitrary arguments would need a procedural macro, which I think is beyond the scope of the question.

You could also use a BufWriter to limit it to a single system call, but it might not be worth the effort.

Peter Hall
  • 53,120
  • 14
  • 139
  • 204