rust-quiz:009-opaque-metavariable.rs
题目
macro_rules! m {
(1) => { print!("1") };
($tt:tt) => { print!("2") };
}
macro_rules! e {
($e:expr) => { m!($e) };
}
macro_rules! t {
($tt:tt) => { e!($tt); m!($tt); };
}
fn main() {
t!(1);
}
关键
和一些泛型类型方法调用类似,不同场景下回转换为不同的类型。
在macro_rules
里面,也会有这种现象。
相关的类型转换和直接透传的类型如下
类型转换
$:block
$:expr
$:item
$:literal
$:meta
$:pat
$:path
$:stmt
$:ty
类型透传
$:ident
$:lifetime
$:tt
题解
m!
macro_rules! m { (1) => { print!("1") }; ($tt:tt) => { print!("2") }; }
这里的主要问题,就是传入的是什么数据。
如果是数值1
,没问题肯定打印的是1
,如果是tt
呢,那就打印2
。e!
macro_rules! e { ($e:expr) => { m!($e) }; }
这里匹配了
expr
,然后传入m!
。
但是expr
隐藏有类型转换的功能,因此传入之后,并非直接数值1
了。
而是token-1
。t!
macro_rules! t { ($tt:tt) => { e!($tt); m!($tt); }; }
这里,有直接的判断打印
m!
,还有一个中间类型转换e!
。
由于传入的是1
,如果是直接调用m!
,那就会直接打印1
。
如果经过e!
的转换,当然必当打印2
。
答案
因此,答案是21
。
本作品采用《CC 协议》,转载必须注明作者和本文链接
expr 隐藏有类型转换的功能,因此传入之后,并非直接数值 1 了。而是 token-1
这个没太理解,token-1是指什么东西?
懂了,参考 doc.rust-lang.org/reference/macros...