【问题标题】:Allow unused named arguments in Rust's format!() family允许 Rust 格式中未使用的命名参数!() 系列
【发布时间】:2017-01-25 00:27:11
【问题描述】:

给定:

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

编译器出现错误退出:

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

通常,这不会是问题,因为应该删除 blue,但我的用例是一个包装宏(简化):

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

有时,它是这样使用的(简化),但其他时候使用不同的颜色,你就会明白要点:

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

编译器退出并出现类似错误:

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

是否可以只忽略未使用的参数,而不是在它们上出错?

【问题讨论】:

    标签: rust


    【解决方案1】:

    如果这组颜色都是已知的,你可以用零长度参数“使用”它们:

    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)

    请注意,字符串 BLUEREDRESET 仍将发送到格式化函数,因此即使不打印任何内容也会产生少量开销。


    我认为这很容易出错,因为如果您忘记了 {reset},控制台的其余部分将变为红色。我想知道为什么不写这样的东西:

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

    【讨论】:

    • "请注意,字符串 BLUE、RED、RESET 仍将被发送",所以如果我使用实现 Display 的事物的实例,它还会调用 Display::fmt 吗? “忘记{reset}其余的”因为我每行任意混合了多种颜色,简单的字符串仅用于演示目的。
    • 感谢回答,带我更新支持库,学习一些关于Rust的新东西Display::fmt
    • @набиячлэвэли:它仍然必须调用Display::fmt,图书馆还不够聪明,无法知道.0 是特殊的(.N 的东西在Display::fmt IIRC 中处理)。跨度>
    • 是的,我想到了,所以我在 Display::fmt() 的实现中对 f.precision() == Some(0) 进行了特殊处理以防止这种情况发生。
    • 显然,这个技巧不适用于Debug 类型,即如果red=SomeNonDisplayType。作为一种解决方法:format!(concat!($fmt, "{red:.0}"), args..., red=format!("{:?}", red))
    猜你喜欢
    • 2016-12-23
    • 1970-01-01
    • 2022-07-06
    • 2017-06-30
    • 1970-01-01
    • 2019-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多