如何使用宏从函数定义集合开始创建函数名称数组?

时间:2016-10-11 20:53:22

标签: macros rust

我想在宏中创建一个数组来转换像:

let array = create_array!(
    fn test() -> i32 { }
    fn test1() { }
);

let array = [test, test1];

我试过了:

macro_rules! create_array {
    () => {
    };
    (fn $func_name:ident () -> $return_type:ty $block:block $($rest:tt)*) => {
        $func_name,
        create_array!($($rest)*);
    };
    (fn $func_name:ident () $block:block $($rest:tt)*) => {
        $func_name,
        create_array!($($rest)*);
    };
}

但它失败并出现以下错误:

error: macro expansion ignores token `,` and any following
  --> src/main.rs:11:19
   |
11 |         $func_name,
   |                   ^
   |
note: caused by the macro expansion here; the usage of `create_array!` is likely invalid in expression context
  --> src/main.rs:27:18
   |
27 |     let array = [create_array!(
   |

我也试过这个:

macro_rules! create_array {
    ($(fn $func_name:ident () $( -> $return_type:ty )* $block:block)*) => {
        [$($func_name),*]
    };
}

但它失败了:

error: local ambiguity: multiple parsing options: built-in NTs block ('block') or 1 other option.
  --> src/main.rs:22:19
   |
22 |         fn test() -> i32 { }
   |

那么如何在这种情况下创建一个数组呢?

1 个答案:

答案 0 :(得分:3)

->$:block的解析歧义已从Rust 1.20版本开始解决,因此您尝试的第二个版本现在可以按预期工作。

macro_rules! create_array {
    ($(fn $func_name:ident () $(-> $return_type:ty)* $block:block)*) => {
        [$($func_name),*]
    };
}

fn main() {
    let test = "TEST";
    let test1 = "TEST1";

    let array = create_array! {
        fn test() -> i32 {}
        fn test1() {}
    };

    println!("{:?}", array);
}