在关于RegexParsers的Scaladoc中,有以下代码:
object Calculator extends RegexParsers {
def number: Parser[Double] = """\d+(\.\d*)?""".r ^^ { _.toDouble }
def factor: Parser[Double] = number | "(" ~> expr <~ ")"
...
我不明白为什么我们用def
而不是val
或lazy val
写的?我会这样写:
object Calculator extends RegexParsers {
lazy val number: Parser[Double] = """\d+(\.\d*)?""".r ^^ { _.toDouble }
lazy val factor: Parser[Double] = number | "(" ~> expr <~ ")"
...
答案 0 :(得分:1)
它有一个实际的语义原因。查看Parser
的类型签名:
abstract class Parser[+T] extends (Input) ⇒ ParseResult[T]
Parser[T]
实际上是一种抽象的Input
到ParseResult[T]
的函数。在许多(可能是大多数)情况下,此函数捕获正在执行的解析状态的某些方面。如果以val
(懒惰或其他方式)捕获此类产品,则不能在给定的解析树中的多个位置使用它。唯一可以制作val
的作品是固定终端,例如标点符号和关键字。
<强>附录强>
自从我使用Scala组合器解析器以来,已经有好几年了,而且当时我还是一个Scala新手,所以完全有可能我错了。但是,我的回忆是Reader
表示整个输入不是输入,而是输入的特定子序列。因此,如果制作没有固定的输入序列,则制作不能是val
。
我确实有一个需要解析器的小方项目,所以当我有时间时,我可以确认或反驳这种理解。