0

因此,当使用 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,那是因为我正在实现一种语言,用户可以在其中定义宏并使用这些宏来定义其他宏。所以不,在有人试图告诉我改变设计之前,我不能。我也真的不想要可变性,因为稍后我将需要多线程。

4

1 回答 1

1

Parser是依赖于路径的类型,因此无法重构此代码,以便可以从构造函数传入 bar。

是的,它可以:

// could also be trait and mixed in where you need it
object MyParsers extends Parsers {
  case class MyParser(bars: List[Parser[String]]) {
    def +(foo: String): MyParser = copy(bars = bars :+ parserFromString(foo))
    ...
  }
}

Parboiled2 会因此受苦吗?他们是否使用依赖路径的类型(乍一看不像)

不,正如您从示例中看到的那样。

如果是这样,为什么 Scala 解析器使用路径相关类型

如上所示,这应该不是问题。在某些情况下,我遇到了与路径相关的类型的麻烦,但在使用解析器时却没有。

对于 Scala 解析器和 parboiled 之间的选择,我个人会更多地考虑性能、您更喜欢哪种 DSL 等。上次我查看 parboiled 时,它没有真正影响错误报告的方法,但现在已修复

于 2015-03-29T08:55:11.010 回答