我正在尝试编写一些自己的调试宏,并正在查看 rusts 构建的源代码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)),+,)
};
}
Run Code Online (Sandbox Code Playgroud)
关于这段代码,有几点让我感到困惑:
$贯穿这段代码的操作符在做什么?($val:expr $(,)?)?我不明白它,是什么以及为什么它在那里。() => {$crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());};?贯穿这段代码的 $ 运算符在做什么?
macro_rules!在普通 Rust 之上有独特的语法。s$用于指示元变量(如$ident)和重复项(如$(...))。您可能应该对 Rust 宏是什么进行一些初步研究:
平面语言相当于什么
($val:expr $(,)?)?我不明白它,是什么以及为什么它在那里。
定义$val:expr将匹配单个表达式的模式。匹配$(,)?a,可能存在零次或一次。有效地使得 willdbg!允许可选的尾随逗号(以便模仿大多数 Rust)。您将看到这一点反映在其他模式中$($val:expr),+ $(,)?。
为什么宏定义以 开头
() => {$crate::eprintln!("[{}:{}]", $crate::file!(), $crate::line!());};?
该宏被设计为使用任意数量的参数(包括零)来调用。该() => { ... };模式允许dbg!()有效。不带参数调用的效果dbg!是仅记录文件和行号。
| 归档时间: |
|
| 查看次数: |
1939 次 |
| 最近记录: |