rust - 基于宏规则生成元组索引!重复扩展

标签 rust macros tuples

给定一个声明性 macro_rules!接受任意数量参数的宏,如何根据重复扩展生成元组索引?
在下面的示例中,我想要 .0在第 6 行和第 7 行生成。

  • 我尝试使用空的“替换”内部宏,例如 (@replace $x:tt) => { $x; } ,但这在元组结构中不起作用。
  • 我意识到我可以将三个语句合二为一,但在我的实际宏中,我也需要中间变量。
  • 我基本上是在寻找相当于 C++ 的 std::integer_sequence

  • macro_rules! the_action {
        (@replace $x:tt) => {$x;};
        
        ($($queue:expr),+) => {
            let iters = ($($queue.iter()),+);
            let options = ($(iters.0.next())*);
            let values = ($(options.0.unwrap_or_default())*);
            
        }
    }
    
    fn main() {
        let a = [1, 4];
        let b = [3, 2];
        let c = [5, -1];
        
        the_action!(a);
        the_action!(a, b);
        the_action!(a, b, c);
    }
    
    Playground link

    额外问题:鉴于 Rust 中缺少可变参数泛型,我希望这在 Rust 中很常见。为什么在 macro_rules 中没有用于重复索引的内置语法?编译器肯定有可用的信息。这是否曾在 RFC 中讨论过?
    编辑:显然 it has ,但看起来它已被搁置。

    最佳答案

    据我所知,使用声明性宏生成它们是不可能的。
    这取决于你的用例,但就目前而言,你可以从以下开始,每次解包元组:

    macro_rules! the_action {
        (@replace $x:tt) => {$x;};
        
        ($($queue:ident),+) => {
            let ($(mut $queue,)+) = ($($queue.iter().copied(),)+);
            let ($($queue,)+) = ($($queue.next(),)+);
            let values = ($($queue.unwrap_or_default(),)*);
            
        }
    }
    
    fn main() {
        let a = [1, 4];
        let b = [3, 2];
        let c = [5, -1];
        
        the_action!(a);
        the_action!(a, b);
        the_action!(a, b, c);
    }
    
    如果您需要访问中间步骤,您可以将它们打包到不同的结构中,如下所示:
    macro_rules! the_action {
        (@replace $x:tt) => {$x;};
        
        ($($queue:ident),+) => {
            {
                struct Step1<$($queue,)+> {
                    $($queue: $queue,)+
                }
                let mut step1 = Step1{$($queue: $queue.iter().copied(),)+};
                struct Step2<$($queue,)+> {
                    $($queue: $queue,)+
                }
                let step2 = Step2{$($queue: step1.$queue.next(),)+};
                let values = ($(step2.$queue.unwrap_or_default(),)*);
            }    
        }
    }
    
    fn main() {
        let a = [1, 4];
        let b = [3, 2];
        let c = [5, -1];
        
        the_action!(a);
        the_action!(a, b);
        the_action!(a, b, c);
    }
    
    一种替代方法是将元组解包到一个数组中,并使用索引——甚至不需要在宏观上创建索引。

    关于rust - 基于宏规则生成元组索引!重复扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66396814/

    相关文章:

    rust - 关于可变内部引用的 Rust 借用规则是什么?

    rust - 缓慢的 SIMD 性能 - 没有内联

    c++ - 从 C++ 中的另一个宏调用多个宏

    python - 元组和递归列表转换

    python - 将元组扩展为参数

    swift - Swift 中的元组与对象

    vector - 如何反向填充向量?

    rust - proc_macro_attribute 函数内部是否存在一致的编译上下文?

    rust - 如何提供可选泛型作为 macro_rules 参数?

    ios - ELEVENWORDINLINE什么时候用呢?