据报道,简单表达式在解析器组合器中是递归的
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
是从String
到Parser[String]
的隐式转换)。
但是 JavaTokenParsers
中的 literal
有参数,而你的没有。所以你可能希望你的只是重载,而不是覆盖,并且不会有冲突 - int
和 literal
之间没有相互递归。
事实上,如果您提供显式类型:
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
,所以它认为递归并放弃。
猜猜这次编译的结果是什么?
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
是从String
到Parser[String]
的隐式转换)。
但是 JavaTokenParsers
中的 literal
有参数,而你的没有。所以你可能希望你的只是重载,而不是覆盖,并且不会有冲突 - int
和 literal
之间没有相互递归。
事实上,如果您提供显式类型:
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
,所以它认为递归并放弃。