当`alt`中的小型解析器无法`move`时,如何重用它们?

问题描述 投票:0回答:1

作为示例,我想解析一个字符串,该字符串可以是 2 个点分隔的单词,也可以是单个单词。每个“单词”都是字母数字和下划线字符的组合,因此我将单词解析器编写为闭包。在任何一种情况下,我都希望解析器函数返回一对单词,其中一个可能是空字符串。对于这个特定问题可能有更好的解决方案,但我只是想在这里激发我的问题。

nom
编写我的解析器,我偶然发现了以下问题:我无法将子解析器编写为闭包(以便重用它们),因为如果我在
alt
中多次使用它们,闭包就会被移动声明:

fn parse_dot_sep_words_or_word(i: &str) -> IResult<&str, (&str, &str)> {
    let word = recognize(many0(alt((alphanumeric1, tag("_")))));
    let dot_sep_word = separated_pair(word, tag("."), word);

    alt((
        map(word, |single_word| ("", single_word)),
        map(dot_sep_word, |(a,b)| (a,b))
    ))
    (i)
}

这不起作用,因为一旦在

word
内部使用
dot_sep_word
就会移动。遵循编译器的说明(“使用 &mut word”)也没有帮助。

我可以使用的唯一解决方案是每次使用

word
时写出
word
的定义。但这似乎与名义提供的优势违反直觉。

我在这里错过了什么?有没有简单的方法可以解决这个问题?

rust closures move nom
1个回答
0
投票

这有点令人惊讶,但是

recognize
不会返回最灵活的类型
impl Fn<..>
但您可以创建一个
Fn
闭包来执行相同的操作:

    let word = |s| recognize(many0(alt((alphanumeric1, tag("_")))))(s);

因为它没有捕获闭包实现的任何环境

Copy
,所以你的其他代码无需任何更改即可工作。

© www.soinside.com 2019 - 2024. All rights reserved.