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

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

import scala.util.parsing.combinator._

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

编译器说@L_404_0@.我的实验说,递归的核心隐藏在文字的声明中!删除它,你会看到递归消失了!

解决方法

JavaTokenParsers定义了一些名为literal的东西.

而rep(“0”)实际上是rep(literal(“0”))(literal是从String到Parser [String]的隐式转换).

但是JavaTokenParsers中的文字需要一个参数,而你的不是.所以你可能会期望你的只是重载,而不是覆盖,并且不存在冲突 – 并且int和literal之间没有相互递归.

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

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

这对编译器来说很好.

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

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

我最好的猜测是,在触发显式返回类型规则时,编译器仍处于相对较早的阶段,它还没有准确地解决什么或不是重载或覆盖.还没有返回类型,它必须基于有关类型的部分信息继续进行.

但它确实知道你的文字定义涉及名称int,你的int定义涉及名称文字,因此它认为递归和放弃.

相关文章

Scala的存在类型 存在类型也叫existential type,是对类型做抽象的一种方法。可以在你不知道具体类型的...
文章目录Option和SomeOption和NoneOption和模式匹配 在java 8中,为了避免NullPointerException,引入了...
文章目录泛类型型变协变逆变不变类型上界类型下界内部类抽象类型复合类型自类型隐式参数隐式转换多态方...
Scala的自定义类型标记 Scala中有很多千奇百怪的符号标记,看起来是那么的独特,就像是一杯dry martini...
文章目录面向对象的scalaUnified TypesClassesTraits 面向对象的scala 我们知道Scala是一种JVM语言,可...
文章目录默认参数值命名参数 scala的参数有两大特点: 默认参数值 命名参数 默认参数值 在Scala中,可以...