使用 Rust 宏简化“匹配”

sim*_*ack 1 macros rust

有许多问题功能(数百个),每个功能可能有不同的类型。对于每个问题,我想运行一个run_question函数,显示该函数花费了多长时间,并打印它的输出。

我正在尝试match使用 Rust 宏来缩短以下表达式(编写run_question100 次确实会使代码变得很长):

fn run_question<T: std::fmt::Display>(question_func: fn() -> T) {
  let begin = Instant::now();
  let output: T = question_func();
  let elapsed_secs = begin.elapsed().as_micros() as f32 / 1e6;
  println!("{}", output);
  println!("{:.6}s taken", elapsed_secs);
}

fn q1() -> u8 { /* ... */ }
fn q2() -> u32 { /* ... */ }
fn q3() -> u64 { /* ... */ }
fn q4() -> String { /* ... */ }

fn main() {
  // ...
  match question_num {
    1 => run_question(q1), 2 => run_question(q2), 3 => run_question(q3), 4 => run_question(q4),
    _ => {
      println!("Question doesn't exist.");
    },
  }
}
Run Code Online (Sandbox Code Playgroud)

我没有编写宏的经验,并尝试了以下不完全有效的方法。它给出了错误:

error: variable 'question_num' is still repeating at this depth
Run Code Online (Sandbox Code Playgroud)

我也很困惑如何将其打印Question doesn't exist.为默认情况。

error: variable 'question_num' is still repeating at this depth
Run Code Online (Sandbox Code Playgroud)

我想使用它的方式是(或者任何简短的都可以):

#[macro_export]
macro_rules! run_questions {
  ( $chosen_question: expr, $( $question_num: expr, $question_mod: expr ), * ) => {
    {
      if $chosen_question == $question_num {
        run_question($question_mod::solve);
      }
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

我读了一些 Rust 的书,但没有那么多宏的例子。

我该怎么做呢?

pro*_*-fh 5

而不是许多if语句,我只是复制了所有可用分支match的重复语句$( ... )*。它似乎表现得像广泛的match表达。

macro_rules! run_questions {
    ( $chosen_question: expr, $( $question_num: expr, $question_mod: expr ), * ) => {
        match $chosen_question {
          $($question_num => run_question($question_mod),)*
          _ => {
                println!("Question doesn't exist.");
          }
        }
    };
}
Run Code Online (Sandbox Code Playgroud)