鉴于macro matching example,这显示了宏如何匹配参数。
我在这里做了很小的改动以使用数字:
macro_rules! foo {
(0 => $e:expr) => (println!("mode X: {}", $e));
(1 => $e:expr) => (println!("mode Y: {}", $e));
}
fn main() {
foo!(1 => 3);
}
作品,打印:mode Y: 3
但是我想使用常量作为参数,可以使它起作用:
const CONST: usize = 1;
macro_rules! foo {
(0 => $e:expr) => (println!("mode X: {}", $e));
(1 => $e:expr) => (println!("mode Y: {}", $e));
}
fn main() {
foo!(CONST => 3);
}
这可能在Rust吗?
注意,使用常规match
语句对我来说是不可用的,因为在我的代码中,每个分支都会解析为不同的类型,从而产生错误。
所以我特别想知道是否可以将常量传递给宏。
答案 0 :(得分:4)
我很确定答案是“不”;在宏扩展时,你所拥有的只是标记树 - 扩展在评估之前发生,甚至是类型推断/检查。
答案 1 :(得分:4)
否强>
宏在Abstract 语法树上运行,因此他们在语法层面上推理:他们推理令牌和他们的拼写。
例如:
fn main() {
let v = 3;
}
在这种情况下,AST看起来像:
fn main
\_ let-binding v
\_ literal 3
如果你问一个宏v
是3
,它会让你看起来很有趣,并想知道你为什么要尝试比较一个变量名和一个文字。
答案 2 :(得分:0)
const CONST: usize = 0;
macro_rules! foo {
($i:ident => $e:expr) => {
if $i == 0 {
println!("mode X: {}", $e);
} else if $i == 1 {
println!("mode Y: {}", $e);
}
};
}
fn main() {
foo!(CONST => 3);
}
如果你想在宏中使用标识符,它需要是 ident
标签,你可以使用 if
, else if
块而不是 match
。