So when using Scala Parsers one may have:
case class MyParser(foos: List[String]) extends Parsers {
val bars: List[Parser[String]] = foos.map(parserFromString)
// Expensive function
def parserFromString(s: String): Parser[String] = ???
}
Parser
is a path-dependent type, so this code cannot be refactored so that bars
can be passed in from the constructor. Note that parserFromString
in my use case actually creates a MyParser
in such a way that MyParser
construction becomes O(N!) where N = foos.size
.
So suppose now I wish to add to bars
via another foo
. The FP way would be to refactor to include bars
in the constructor, then define something like def +(foo: String): MyParser = copy(bars = bars :+ parserFromString(foo)
, but as mentioned I can't I have to recreate from scratch.
My solution is just make bars
a private var
and mutate it with a Unit
method update
, i.e. def update(foo: String): Unit = bars +:= parserFromString(foo)
My first question is quite simple: am I stuck? Do I have to use mutation?
Second question: does Parboiled2 suffer from this? Do they use path-dependent types (at a glance it doesn't look like it), and if so why do Scala parsers use path-dependent types?
If parboiled2 does not suffer from path-dependent types this alone can be a reason to use it!
If anyone is wondering why I need to create Parser
s from parameters it's because I'm implementing a language where users can define macros and use those macros in defining other macros. So no, before anyone tries telling me to change the design, I can't. I also really don't want mutability since I'm going to be needing multi-threading later.
Yes, it can:
No, as you can see from the examples.
As shown above, this shouldn't be a problem. I have run into trouble with path-dependent types in some circumstances, but not in use of parsers.
For choice between Scala-parsers and parboiled, I'd personally think more about performance, which DSL you prefer, etc. Last time I've looked at parboiled, it had no real way to affect error reporting, but this is fixed now.