Skip to content

Consider renaming function Count #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
marco-m opened this issue Sep 16, 2022 · 4 comments
Open

Consider renaming function Count #7

marco-m opened this issue Sep 16, 2022 · 4 comments
Assignees
Labels
enhancement New feature or request

Comments

@marco-m
Copy link

marco-m commented Sep 16, 2022

Salut Théo,
consider:

// Count runs the provided parser `count` times.
func Count()...

Although I am not a native English speaker, I think that the name Count in this case is misleading. I read it as "count the number of occurrences of something and give me back the result", that is, as a verb in the imperative tense.

According to the documentation, I would call it something like ApplyN().

@oleiade oleiade self-assigned this Sep 26, 2022
@oleiade
Copy link
Owner

oleiade commented Sep 26, 2022

Salut @marco-m 👋🏻

Sorry for the delay in my answer, I was not around computers 🌴

I fully agree with you. The Count combinator could be renamed. I used the same name as in the nom library, but I must admit I never found it intuitive myself.

Now, for alternative names, I think it's going to be tricky indeed, but it's worth giving a try 🤞🏻

First and foremost, I must say I'm against ApplyN, I see where you're coming from with it, and it could be a good candidate indeed. However, the term Apply has a strong connotation in the functional programming world, and I believe refers (also in set theory) to something else completely. Besides, Apply would probably be misleading in the context of parser combinators, as calling it wouldn't "apply" a parser, but rather build a parser; it's a fine-grained difference, but I believe it matters.

Here are some alternatives I could think of, let me know what you think, and please feel free to propose others:

  • ManyN: fits in the existing namespace, and expresses the fact that a parser would be expected to match N times. The main downside I see is that we use Many in a context where we don't know how many matches we expect to find beforehand, and that might feel contradictory.
  • ExactlyN: addresses the issue with ManyN being unclear as to its behavior when encountering less or more than N matches. One downside I see is that Exactly carries an expectation that's broader than just numerical (find N matches), and could be misinterpreted.
  • TupleN: is probably more abstract, but also somewhat the most accurate I can think of "I want to produce a parser that parses exactly N times the provided parser, and returns the result as a Tuple of size N". The actual return value could even be a slice in the first place.

Let me know what you think 👀

@oleiade oleiade added the enhancement New feature or request label Sep 26, 2022
@marco-m
Copy link
Author

marco-m commented Sep 26, 2022

Ah, naming is indeed difficult! :-)

I was not aware that Count was somewhat the established name, since it is used by the non library. Maybe that is a good enough justification to live with it? Consistency can be indeed important...

Otherwise, I tried to uniformize a bit the description of the 3 functions in multi.go. Remember that I don't really know what I am describing (although I am familiar with classic formal languages and parsing, I am not familiar with parser combinators :-) ).

I can offer the following:

  • Many0 constructs a parser that will run repeatedly until it fails, and will returns a slice of all the results as the Result's Output. [...]
  • Many1 constructs a parser that will run repeatedly until it fails, and will return a slice of all the results as the Result's Output. Many1 will fail if the parser fails to match at least once. [...]

If these two make sense, then following your suggestion for ManyN, we could have something like:

  • ManyN constructs a parser that will run until it fails or it reaches N iterations, and will returns a slice of all the results as the Result's Output. [...]

I have to say that I am a bit uncertain, because for Many0 and Many1, if I understood correctly, the number means: "number of failures" (or something along these lines), while for ManyN, the number would mean "number of iterations" ...

@oleiade
Copy link
Owner

oleiade commented Oct 4, 2022

So, it took me some time, but I've been thinking hard about this, and let my brain do the rest in the background. What I ended coming up with was the following:

  • Many comes with the assumption that you don't already know how many you actually expect to find. Whereas the Count combinator is dedicated to ensuring a parser P matches exactly N times. So in hindsight, I would disqualify the Many idea. Would you agree?
  • In hindsight, I kinda like the idea of having a ManyN combinator though: " will run until it fails or it reaches N iterations". I don't think this is covered completely by any of the existing combinators, though wonder if it does not overlap too much with TakeWhileMN though? What do you think? If you believe ManyN makes sense, could you open a dedicated issue for it? 🙏🏻
  • The option that appears the most explicit to me after sleeping on it a bunch of times would be: Repeat(p Parser, n int) (or Repeated). It conveys the actual behavior quite nicely: "the behavior of this parser is gonna be repeated N times", and as a user wondering how I would build a parser that parser 6 numbers, for instance, I would find it more intuitive than Count for instance. What do you think @marco-m ? 😄

@marco-m
Copy link
Author

marco-m commented Oct 4, 2022

Repeat is a good one indeed (which reminds me of... ApplyN 😉), I would go for it. Is more intuitive than Count and is more precise than ManyN.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants