rust-quiz:009-opaque-metavariable.rs

godme發表於2022-07-11
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 協議》,轉載必須註明作者和本文連結

相關文章