0

在关于RegexParsers 的Scaladoc 中,有以下代码:

object Calculator extends RegexParsers {
  def number: Parser[Double] = """\d+(\.\d*)?""".r ^^ { _.toDouble }
  def factor: Parser[Double] = number | "(" ~> expr <~ ")"
...

我不明白为什么我们用 adef而不是 a valor a来写它lazy val?我会这样写:

object Calculator extends RegexParsers {
  lazy val number: Parser[Double] = """\d+(\.\d*)?""".r ^^ { _.toDouble }
  lazy val factor: Parser[Double] = number | "(" ~> expr <~ ")"
...
4

1 回答 1

1

它有一个实际的语义原因。查看类型签名Parser

 abstract class Parser[+T] extends (Input) ⇒ ParseResult[T]

Parser[T]实际上是从某种抽象类型Input到 a的函数ParseResult[T]。在许多(可能是大多数)情况下,此函数捕获正在执行的解析状态的某些方面。如果在 , 中捕获了这样的产生val式(惰性或其他方式),则它不能在给定解析树中的多个位置使用。唯一可以制作val的是固定的终端,例如标点符号和关键字。

附录

自从我从事 Scala 组合解析器工作以来已经有好几年了,而且我当时还是一个 Scala 新手,所以我完全有可能只是弄错了。然而,我的回忆是,它Reader代表的不是整个输入,而是该输入的特定子序列。因此,如果生产没有固定的输入序列,则生产不可能是val.

实际上,我确实有一个需要解析器的小项目,所以当我有时间时,我可以确认或反驳这种理解。

于 2013-10-18T16:19:08.297 回答