liveBook · Manning

listOfN

As explained in Functional Programming in Scala, Second Edition

listOfN is a parser combinator that parses a specified number of occurrences of another parser and returns their results as a list.

listOfN repeats a parser exactly a specified number of times and collects the parsed values in order. A parser for either "ab" or "cad", followed by listOfN(3), accepts three consecutive alternatives and returns a List[String]. The combinator is parametric: the repeated parser may produce strings, characters, or any other result type. section 9.1

Parsing exactly three alternatives

Given p = (string("ab") | string("cad")).listOfN(3), input "ababcad" produces List("ab", "ab", "cad"); "cadabab" and "ababab" also succeed with their three parsed pieces. Unlike an unbounded repetition combinator, the count is fixed before parsing begins. section 9.1 section 9.8

The recursive design mirrors the required count. For n <= 0, succeed with an empty list. Otherwise, parse one value with p, recursively parse n - 1 more values, and use map2 with cons to prepend the first result. This makes the list structure correspond directly to the sequence consumed from input. section 9.8

listOfN is closely related to many: both accumulate repeated parser results, but many stops when parsing no longer succeeds whereas listOfN has an explicit limit. Recursive repetition also exposes an evaluation concern: a strict second argument to map2 can construct recursive parsers too early, so parser combinators may make that argument nonstrict or defer it. section 9.8

The same collection pattern also appears in generators. A Gen[A].listOfN(n) creates n copies of a generator and sequences them, turning List[Gen[A]] into Gen[List[A]]. When the size itself is generated, flatMap selects the corresponding fixed-size generator after producing the size. section 8.1.4 section 8.6

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Derives recursive behavior with map2 and succeed, and identifies nonstrictness or defer as the remedy for eager recursive construction.
Examples
Demonstrates three parses of "ab" or "cad" and parses a generated count of consecutive 'a' characters.
What it assumes
Introduces repetition after basic parser alternatives while relying on map2, succeed, and recursive calls for the implementation.
What you can do after
Build it from scratch as a recursive parser combinator and adapt the collection pattern to generators.
How it connects
Connects fixed repetition to many, map2, succeed, defer, flatMap, State, and generators.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.