为什么我不能在 tuple() 中使用同一个解析器两次?

Why can't I use the same parser twice in a tuple()?

我编写了以下 nom 解析器代码:

use nom::character::complete::digit1;
use nom::combinator::map_res;
use nom::error::Error;
use nom::sequence::tuple;
use nom::Err;

type E<'a> = Err<Error<&'a str>>;

fn parse_double_int(input: &str) -> Option<(i32, i32)> {
    let num = map_res(digit1, |s: &str| s.parse::<i32>());
    let mut pair = tuple((num, num));
    let res: Result<_, E> = pair(&input.trim());

    match res {
        Ok((_, (a, b))) => Some((a, b)),
        Err(_) => None,
    }
}

错误:

error[E0382]: use of moved value: `num`
  --> src\lib.rs:11:32
   |
10 |     let num = map_res(digit1, |s: &str| s.parse::<i32>());
   |         --- move occurs because `num` has type `impl FnMut<(&str,)>`, which does not implement the `Copy` trait
11 |     let mut pair = tuple((num, num));
   |                           ---  ^^^ value used here after move
   |                           |
   |                           value moved here

For more information about this error, try `rustc --explain E0382`.

如何重用我在本地定义的解析器?

你正在“移动值”意味着 Rust 正在赋予你的值 num 的所有权,然后在它完成时释放它(删除它),你可以尝试让你的函数使用 &num 符号借用该值,或者如果结构实现了克隆特性,则克隆变量。 有一个类似的问题 我无法仅用代码片段重现您的问题,但希望这能为您提供足够的信息来找到解决方案!

map_resreturn一个FnMut。你不能移动两次 FnMut 因为 FnMut 没有实现 Copy,比明显的解决方案是借用它,但你不能因为 Parser 需要mut 并且您不能有多个可变借用。所以最后一个选择是实现一个 Parser 来实现 Copy 或者可以很容易地创建:

FnMut 包裹在 Fn 闭包中,实现复制:

let num = |input| map_res(digit1, |s: &str| s.parse::<i32>())(input);

创建函数:

fn num(input: &str) -> IResult<&str, i32> {
  map_res(digit1, |s: &str| s.parse::<i32>())(input)
}