Rust 函数语法问题,示例似乎在 nom

问题描述

我正在查看用于 rust 的 nom 板条箱,其中包含许多用于解析字节/字符的函数

许多函数,例如下面看到的 tag(),处理的输入不是作为函数的参数提供的,而是出现在第二组括号中,在我称之为参数的后面。在示例中,如果人们在 haystack 中寻找 needle,那么 tag() 函数使用它自己的参数,这就是如何指定 em>needle,但是haystack是单独指定的,在参数括号之后,在它自己的括号里面(可能是因为它是一个单值元组?)。

use nom::bytes::complete::tag;

fn parser(s: &str) -> IResult<&str,&str> {
  tag("Hello")(s)
}

在上面的示例中,tag() 的工作是测试输入 s 是否以 Hello 开头。您可以调用parser,传入“大家好!tag() 函数确实验证了s 的开头是Hello em>。但是(s)是如何进入tag()的?

有人可以向我解释这个语法,或者告诉我在哪里可以阅读它。它有效,我可以使用它,但我不明白我在看什么!

谢谢

解决方法

tag() 的返回值为 impl Fn(Input) -> IResult<Input,Input,Error>,即函数返回另一个函数。第一组括号用于调用 tag();第二组用于调用它返回的函数。

这允许您将这些函数返回的“解析器”存储在一个变量中并多次使用它。或者,换句话说,您也可以编写

,而不是问题中的函数定义
let parser = tag("Hello");

然后像调用函数一样调用 parser

,

tag("Hello") 只返回一个函数,然后立即使用参数 s 调用该函数,即 tag("Hello")(s)。这是一个简单的实现示例:

fn tag<'a>(needle: &'a str) -> impl Fn(&str) -> bool + 'a {
    move |haystack: &str| haystack.starts_with(needle)
}

fn parser(s: &str) -> bool {
    tag("Hello")(s)
}

fn main() {
    println!("{}",parser("Hello everbody!")); // true
    println!("{}",parser("Bye everybody!")); // false
}

playground