因此,当使用 Scala 解析器时,可能会有:
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
是依赖路径的类型,因此无法重构此代码,以便bars
可以从构造函数传入。请注意,parserFromString
在我的用例中,实际上创建 aMyParser
的方式使得MyParser
构造变为 O(N!) where N = foos.size
。
所以假设现在我希望bars
通过另一个foo
. FP 方法是重构以包含bars
在构造函数中,然后定义类似的东西def +(foo: String): MyParser = copy(bars = bars :+ parserFromString(foo)
,但如前所述,我不能从头开始重新创建。
我的解决方案就是制作bars
一个private var
并用一种Unit
方法对其进行变异update
,即def update(foo: String): Unit = bars +:= parserFromString(foo)
我的第一个问题很简单:我被卡住了吗?我必须使用突变吗?
第二个问题:Parboiled2 会因此受苦吗?他们是否使用依赖于路径的类型(乍一看不像),如果是这样,为什么 Scala 解析器使用依赖于路径的类型?
如果 parboiled2 不受路径依赖类型的影响,仅此一项就可以成为使用它的理由!
如果有人想知道为什么我需要Parser
从参数创建 s,那是因为我正在实现一种语言,用户可以在其中定义宏并使用这些宏来定义其他宏。所以不,在有人试图告诉我改变设计之前,我不能。我也真的不想要可变性,因为稍后我将需要多线程。