据报道,简单表达式在解析器组合器中是递归的

Simple expression is reportedly recursive in parser combinators

猜猜这次编译的结果是什么?

import scala.util.parsing.combinator._

object ExprParser extends JavaTokenParsers {
    lazy val literal = int  
    lazy val int = rep("0")
}

编译器说 int is recursive and asks for the type of it。我的实验说递归的核心隐藏在字面量的声明中!去掉它,你会发现递归没有了!

这里相关的是 JavaTokenParsers 定义了一个叫做 literal 的东西。

rep("0")实际上是rep(literal("0"))literal是从StringParser[String]的隐式转换)。

但是 JavaTokenParsers 中的 literal 有参数,而你的没有。所以你可能希望你的只是重载,而不是覆盖,并且不会有冲突 - intliteral 之间没有相互递归。

事实上,如果您提供显式类型:

object ExprParser extends JavaTokenParsers {
  lazy val literal: Parser[List[String]] = int 
  lazy val int: Parser[List[String]] = rep("0")
}

编译器运行良好。

那么为什么在省略 return 类型时会触发显式 return 类型的递归规则?

我认为这是一个相当微妙的问题。我不确定我确切地知道这里发生了什么。我在涵盖它的 Scala 语言规范中找不到特定语言。

我最好的猜测是,在触发显式 return 类型规则时,编译器仍处于相对较早的阶段,尚未解决究竟是什么或不是过载或覆盖。还没有 return 类型,它必须根据有关类型的部分信息进行处理。

但是它确实知道你定义的literal涉及名字int,而你定义的int涉及名字literal,所以它认为递归并放弃。