On Mon, Jul 25, 2016 at 12:21 PM, Daniel Bünzli <daniel.buenzli@erratique.ch> wrote:
You are making a lot of assumptions about how the client should use the library or what humans are supposed to tolerate…

Nope, just one or two that seem pretty reasonable. First, there's not much else a client of a parser can do with those errors without breaking conceptual abstraction boundaries. Any action that a client would want to take that wasn't logging properly belongs in the parser itself. A design to the contrary would require the client of the parser to embody knowledge of the parsing process itself, which defeats modularity, reuse, and ultimately kills compositionality. So the only client assumption is that the client finds these sorts of properties desirable.

Second, I'm well aware of human tolerances for feedback latency. Such topics have been making the rounds in The New York Times, pop design books, and the blogosphere for more than a decade now, so it's hardly an obscure topic. I've also built and commercialized systems for application performance management, which required a deep understanding of end-user experience, business use cases, and operational practices.

The design I described has worst case failure reporting latency not exceeding the latency of a successful parse. If you're exceeding those latency tolerances at the parsing step, there is no hope of redemption for the latency of the rest of your pipeline. And these aren't even catastrophic failures. As you describe them they're, more or less, warnings.
 
Giving back control to the client in case of error and allow it to restart the process allows to lift the constraints you put on the client.

While such a design sometimes benefits the system _as a whole_, it certainly comes at a cost. In the case where clients are meant to explicitly handle parse errors and restart the parse _through control inversion_, the cost is the compositionality. That may be a worthwhile cost to pay in some cases, but those cases have not yet revealed themselves to me. On the other hand, Angstorm allows you to construct parsers compositionally, and reuse them in just the same way. It even allows users to design parsers that will report parse warnings, or even receive certain kinds of errors are return a decision (that the parser is designed to understand) about how to proceed. Whether or not that's a worthwhile design is another question. I would say it's not but there's no accounting for taste. For supporting composition, it's certainly better than control inversion.

To bring it back, I think this discussion is focusing a bit too much on the implementation of a single Angstrom parser, rather than the capabilities of the library as a whole. Angstrom can suit the needs of many architectural styles, whether its a "direct" style or "streaming" style, or that leads to parsers that give clients fine-grained control over error recovery. It's a parser combinator library, after all. Your parsers can do whatever you design them to do, take whatever parameters they need to, and following a few rules of thumb, still deliver good performance.

-Spiros E.