1

I'm looking at the nom crate for rust, which contains lots of functions to parse bytes/characters.

Many of the functions, such as tag(), seen below, process input that's provided not as a parameter to the function, but that appears instead in a second set of parentheses, following what I would call the parameters. If, in examples, one looks for a needle in a haystack, then the tag() function uses a parameter of its own, which is how one specifies the needle, but the haystack is specified separately, after the parameter parentheses, inside parentheses of its own (perhaps because it's a single value tuple?).

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

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

In the example above, tag()'s job is to test whether the input s starts with Hello. You can call parser, passing in "Hello everybody!, and the tag() function does indeed verify that the start of s is Hello. But how did (s) find its way into tag()?

Can someone explain this syntax to me, or show where to read about it. It works, and I can use it, but I don't understand what I'm looking at!

thanks

2 Answers 2

2

The return value of tag() is impl Fn(Input) -> IResult<Input, Input, Error>, i.e. the function returns another function. The first set of parentheses is for calling tag(); the second set is for calling the function it returns.

This allows you to store the "parser" returned by these functions in a variable and use it multiple times. Or, put differently, instead of the function definition in your question you could also write

let parser = tag("Hello");

and then call parser the same way you would call the function.

Sign up to request clarification or add additional context in comments.

1 Comment

Perfect. Thanks. I thought the complicated function definition somehow did something to isolate one parameter, such that it would not be passed in in the usual way, but I see now, that the result is a function, and we're just calling that function. Thanks.
0

tag("Hello") just returns a function, which is then immediately invoked with the argument s, i.e. tag("Hello")(s). Here's a simple implementation example:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.