macro_rules! thisis {
($t: ty) => {
println!("this is a type")
};
($t: ident) => {
println!("this is an ident")
};
}
fn main()
{
const variable: i32 = 32;
thisis!(i32);
thisis!(variable);
}
在上面的例子中,打印"这是一个类型",在这两种情况下,它并没有真正识别类型和标识之间的区别。无论哪个定义先出现,它都会出现。
宏不是上下文敏感的。宏不知道给定的名称是当前作用域中的变量还是类型。它只知道它可以从语言的上下文无关语法中收集到什么,并且根据这些规则,i32
和variable
都是有效的类型和/或标识符名称。
具体来说,Rust引用如下定义ty
和ident
。
ty
: aTypeident
:一个IDENTIFIER_OR_KEYWORD或RAW_IDENTIFIER
其中类型被定义为几个东西,但其中之一是TypePath,它实际上是由::
连接的任何标识符字符串。
IDENTIFIER_OR_KEYWORD,顾名思义,是Rust中任何有效的标识符名称,或Rust关键字。RAW_IDENTIFIER是一个以r#
为前缀的标识符(包括关键字)(这允许我们,例如,将if
作为变量名,将其写成r#if
foo
这样的普通标识符根据Rust的语法规则既是ty
又是ident
。像foo::bar
这样的限定名称只有ty
而不是ident
。同时,像while
或if
这样的语言关键字(将写成没有原始标识符r#
前缀的)将是ident
而不是ty
。不幸的是,你只是在宏观层面上没有这种层次的语义信息。