首页 > 解决方案 > 了解dbg!Rust 中的宏

问题描述

我正在尝试编写一些自己的调试宏,并且正在查看 rusts build in 的源代码dbg!

macro_rules! dbg {
    () => {
        $crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());
    };
    ($val:expr $(,)?) => {
        // Use of `match` here is intentional because it affects the lifetimes
        // of temporaries - https://stackoverflow.com/a/48732525/1063961
        match $val {
            tmp => {
                $crate::eprintln!("[{}:{}] {} = {:#?}",
                    $crate::file!(), $crate::line!(), $crate::stringify!($val), &tmp);
                tmp
            }
        }
    };
    ($($val:expr),+ $(,)?) => {
        ($($crate::dbg!($val)),+,)
    };
}

这段代码有几件事让我感到困惑:

  1. $贯穿这段代码的操作员在做什么?
  2. 平面语言相当于($val:expr $(,)?)什么?我不明白,它是什么以及它为什么在那里。
  3. 为什么宏定义以 开头() => {$crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());};

标签: rust

解决方案


贯穿这段代码的 $ 运算符在做什么?

macro_rules!在普通 Rust 之上具有不同的语法。$s 用于表示元变量(like )$ident和重复(like $(...))。您可能应该对 Rust 宏是什么做一些初步研究:


平面语言相当于($val:expr $(,)?)什么?我不明白,它是什么以及它为什么在那里。

$val:expr定义将匹配单个表达式的模式。$(,)?匹配的 a可能,存在零次或一次。有效地使它dbg!允许可选的尾随逗号(以模仿大多数 Rust)。您会在其他模式中看到这一点$($val:expr),+ $(,)?


为什么宏定义以 开头() => {$crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());};

该宏被设计为使用任意数量的参数调用,包括零。该() => { ... };模式允许dbg!()有效。不带参数调用的效果dbg!是只记录文件和行号。


推荐阅读