rust - 将宏扩展为元组初始化

标签 rust macros metaprogramming

我的目标是制作一个能够以描述元组初始化的方式扩展的宏。

我做了这个玩具示例:

macro_rules! fill_tuple {
    ($_idx : expr) => {};
    ($idx : expr, $kind : ident) => {
        $idx
    };
    ($idx : expr, $head : ident, $($tail : ident),+) => {
        fill_tuple!($idx, $head),
        fill_tuple!($idx + 1usize, $($tail),+)
    };
}

fn main()
{
    (
    fill_tuple!(0usize, A,B,C)
    )
}

这里的思路是,有3个参数,展开后应该得到(0, 1, 2)。这只是一个示例,最后我将以更复杂的方式实际使用 A、B、C 来初始化元组。

我目前的障碍是宏最后一 block 的逗号不被 rust 接受。我收到错误:

Compiling playground v0.0.1 (/playground)
error: macro expansion ignores token `,` and any following
  --> src/main.rs:7:33
   |
7  |         fill_tuple!($idx, $head),
   |                                 ^
...
15 |     fill_tuple!(0usize, A,B,C)
   |     --------------------------- help: you might be missing a semicolon here: `;`
   |     |
   |     caused by the macro expansion here
   |
   = note: the usage of `fill_tuple!` is likely invalid in expression context

我该如何解决这个问题?我绝对需要那个逗号,否则整个生成的代码都是错误的。

最佳答案

您可以递归地遍历宏参数并保留结果数字的列表。

macro_rules! fill_tuple {
    // Base cases
    (@step 0, (),) => {
        ()
    };
    (@step $i:expr, ($($result:expr),*), $head:expr) => {
        ($($result,)* foo($i, $head),)
    };

    // Recursive case
    (@step $i:expr, ($($result:expr),*), $head:expr, $($tail:expr),+) => {
        fill_tuple!(@step $i + 1, ($($result,)* foo($i, $head)), $($tail),+)
    };

    // Public interface
    ($($e:expr),*) => {
        fill_tuple!(@step 0, (), $($e),*)
    };
}

如果不需要索引,那就简单多了:

macro_rules! fill_tuple {
    ($($e:expr),*) => {
        ($(bar($e),)*)
    }
}

关于单元素元组有一些微妙的细节,因为您必须将值放在括号中并在值后紧跟一个逗号——例如,(7,) 而不是 (7)。所以在第一个宏中,我们需要在 ($($result,)* foo($i, $head),) 行的 foo() 之后加上逗号。同样,在第二个宏中,我们需要 ($(bar($e),)*) 而不是 ($(bar($e)),*) 以便每个值后面都有一个逗号,而不是每个值(最后一个除外)。

关于rust - 将宏扩展为元组初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73677012/

相关文章:

javascript - 如何使用 sweet.js 编译多个文件?

macros - 在 emacs lisp 中定义 let 宏作用域

c++ - 如何在结构/类中获取有关 "current type"的信息?

Ruby 元类疯狂

c++ - 元整数平方根中的无限递归

rust - 为什么元组结构和枚举变体的行为类似于函数

rust - `dyn` 和泛型有什么区别?

使用参数 vector 调用函数的 C++ 模板

arrays - 如何创建超过 32 个泛型类型元素的数组 T : Default?

parsing - 是否可以为任意类型派生一个解析相应调试格式的解析器?