Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow unused named arguments in Rust's format!() family

Tags:

rust

Given:

format!("{red}{}{reset}", "text", red = "RED", blue = "BLUE", reset = "RESET");

The compilers exits with an error:

error: named argument never used
  --> example.rs:1:47
   |
 1 |         format!("{red}{}{reset}", "text", red = "RED", blue = "BLUE", reset = "RESET");
   |                                                        ^^^^^^^^^^^^^

Normally, this wouldn't be a problem as blue should be removed, but my usecase is a wrapper macro (simplified):

macro_rules! log {
    ($fmt:expr, $($arg:tt)*) => {
        println!($fmt, $($arg)*, blue = "BLUE", red = "RED", reset = "RESET");
    };
}

Sometimes, it is used like this (simplified), but other times with different colours, you get the gist:

log!("{red}{}{reset}", "text");

The compiler exits with an analogous error:

error: named argument never used
  --> example.rs:3:26
   |
3  |         println!($fmt, $($arg)*, blue = "BLUE", red = "RED", reset = "RESET");
   |                                  ^^^^^^^^^^^^^

Is it possible to just ignore the unused arguments, instead of erroring on them?

like image 376
набиячлэвэли Avatar asked Jan 25 '17 00:01

набиячлэвэли


1 Answers

If the set of colors are all known, you could "consume" them with zero-length arguments:

macro_rules! log {
    ($fmt:expr, $($arg:tt)*) => {
        println!(concat!($fmt, "{blue:.0}{red:.0}{reset:.0}"),  // <--
                 $($arg)*,
                 blue="BLUE", 
                 red="RED", 
                 reset="RESET")
    }
}

fn main() {
    log!("{red}{}{reset}", "<!>");
    // prints: RED<!>RESET
}

(Docs for concat! macro)

Note that the strings BLUE, RED, RESET will still be sent to the formatting function, so it will incur a minor overhead even nothing will be printed.


I think this is quite error prone, since if you forget a {reset} the rest of your console will become red. I wonder why not write something like:

macro_rules! log_red {
    ($fmt:expr, $($arg:tt)*) => {
        println!(concat!("RED", $fmt, "RESET"), $($arg)*);
    }
}
// also define `log_blue!`.

log_red!("{}", "text");
like image 55
kennytm Avatar answered Nov 05 '22 04:11

kennytm