You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Rust宏编译时反转vec2列表遇语法错误求助

编译时反转Vec2列表的Rust宏语法错误解决

问题描述

尝试编写point_reverser宏在编译时反转二维点列表,设计三个递归分支:

  • 初始化空的已反转列表,分离待反转与已处理列表;
  • 递归将主列表头部元素移至已反转列表尾部;
  • 主列表为空时返回结果。

但运行时出现no rules expected the token ','错误,调整分支顺序无效。代码及错误信息如下:

原代码

macro_rules! point_reverser {
    ([$([$x:expr, $y:expr]),*]) => {
        point_reverser!([$([$x, $y]),*] reversed: [])
    };
    ([[$x:expr, $y:expr], $([$x_head:expr, $y_head:expr]),*] reversed: [$([$x_tail:expr, $y_tail:expr]),*]) => {
        point_reverser!([$([$x_head, $y_head]),*] reversed: [$([$x_tail, $y_tail]),* , [$x, $y]])
    };
    ([[$x:expr, $y:expr]] reversed: [$([$x_tail:expr, $y_tail:expr]),*]) => {
        [$([$x_tail, $y_tail]),* , [$x, $y]]
    };
}

fn main() {
    let reversed_points = point_reverser!([[1, 2], [3, 4], [5, 6]]);
    println!("{:?}", reversed_points);
    println!("Expected result: [[5, 6], [3, 4], [1, 2]]");
}

错误信息

error: no rules expected the token `,`
  --> src\main.rs:6:85
   |
1  | macro_rules! point_reverser {
   | --------------------------- when calling this macro
...
6  |         point_reverser!([$([$x_head, $y_head]),*] reversed: [$([$x_tail, $y_tail]),*, [$x, $y]])
   |                                                                                     ^ no rules expected this token in macro call
...
13 |     let reversed_points = point_reverser!([[1, 2], [3, 4], [5, 6]]);
   |                           ----------------------------------------- in this macro invocation
   |
note: while trying to match `]`
  --> src\main.rs:5:106
   |
5  |     ([[$x:expr, $y:expr], $([$x_head:expr, $y_head:expr]),*] reversed: [$([$x_tail:expr, $y_tail:expr]),*]) => {
   |                                                                                                          ^
   = note: this error originates in the macro `point_reverser` (in Nightly builds, run with -Z macro-backtrace for more info)

错误原因分析

  1. 重复模式逗号处理错误:递归调用中[$([$x_tail, $y_tail]),* , [$x, $y]]的写法违反宏规则,$(...),*会自动在每个元素后加逗号,当已反转列表为空时,会生成, [$x, $y]这种开头带逗号的非法格式,无法被分支匹配。
  2. 分支覆盖不全:缺少主列表为空时的终止分支,当前第三个分支仅处理主列表剩单个元素的情况,递归逻辑不完整。

修正后的代码

macro_rules! point_reverser {
    // 初始化分支:接收待反转列表,启动递归
    ([$([$x:expr, $y:expr]),*]) => {
        point_reverser!([$([$x, $y]),*] reversed: [])
    };

    // 递归分支:主列表有多个元素,将头部移到已反转列表开头
    ([[$x:expr, $y:expr], $([$x_head:expr, $y_head:expr]),*] reversed: [$($reversed:tt),*]) => {
        point_reverser!([$([$x_head, $y_head]),*] reversed: [[$x, $y], $($reversed),*])
    };

    // 递归分支:主列表只剩单个元素,合并到已反转列表
    ([[ $x:expr, $y:expr ]] reversed: [$($reversed:tt),*]) => {
        [[$x, $y], $($reversed),*]
    };

    // 终止分支:主列表为空,直接返回已反转列表
    ([] reversed: [$($reversed:tt),*]) => {
        [$($reversed),*]
    };
}

fn main() {
    let reversed_points = point_reverser!([[1, 2], [3, 4], [5, 6]]);
    println!("{:?}", reversed_points); // 输出: [[5, 6], [3, 4], [1, 2]]
    println!("Expected result: [[5, 6], [3, 4], [1, 2]]");
}

关键修正点

  • 调整元素添加逻辑:将新元素放在已反转列表的开头,避免末尾添加时的逗号冲突,简化重复模式处理。
  • 补充终止分支:新增主列表为空的匹配分支,确保递归能正确终止。
  • 简化匹配器:用$reversed:tt匹配已反转元素,避免重复编写复杂的二维点模式,提升宏的可读性。

内容的提问来源于stack exchange,提问作者jakebird451

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 12:59:54