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 协议》,转载必须注明作者和本文链接
讨论数量: 3

expr 隐藏有类型转换的功能,因此传入之后,并非直接数值 1 了。而是 token-1
这个没太理解,token-1是指什么东西?

3周前 评论
godme (楼主) 3周前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!