加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

解析 – scalac缺少关闭括号错误报告与奇怪的行号

发布时间:2020-12-16 18:51:26 所属栏目:安全 来源:网络整理
导读:因为我一直在学习 Scala,所以当读取scalac的神秘输出时,我经常会想到编译错误.然而,今天我遇到了一些我怀疑即使在宇宙中也会发生的事情. 一位朋友给我发了一个非常简单的代码片段,其中包含一个相当常见的错误: case class Var(name: String) extends ArithE
因为我一直在学习 Scala,所以当读取scalac的神秘输出时,我经常会想到编译错误.然而,今天我遇到了一些我怀疑即使在宇宙中也会发生的事情.

一位朋友给我发了一个非常简单的代码片段,其中包含一个相当常见的错误:

case class Var(name: String) extends ArithExpr {
  override def eval(env: Env) =  env.lookup(name) match {
    case Some(d) => d
    case None => throw new IllegalArgumentException("Env " + env + " does not contain a binding for " + name)
  }
  override def exprString = name
// } // <-- MISSING THIS BRACE

完整的源文件is posted here.由于case类Var类声明缺少其右括号,你会认为编译器会告诉你该声明的开头大括号(第11行)缺少它的右大括号.但是,scalac报告它在前一个案例类声明的中间“假设”缺少右括号(在第7行). (完整的错误输出包含在发布的代码的底部.)

如果您了解语言的内部,大多数scalac错误消息都有意义,但我在这里完全失去了.在后面的类声明中,缺少的右括号如何最终传播到文件中较早的已成功解析的类定义?

你到底如何向Scala初学者解释这个问题?离开一个右大括号正是Scala新手常常会犯的那种错误,但是这里的错误信息似乎会导致用户误入歧途,报告像错误这样的东西可能更有帮助:你似乎反而错过某个地方的’}’.

注意:我知道像这样的问题的通常答案只是“使用IDE并且增量编译将立即标记它”或“语法突出显示应该使此错误显而易见” – 但我的问题是具体询问scalac输出,所以请记住,我知道这些是有效点,但我真的只是想了解编译器在这里发生了什么.

更新:

让我尝试一种不同的方法来解释我的困惑.错误源于缺少右括号,所以它显然是支撑嵌套的问题.转换我发布到一系列行号括号对的片段中的文本(代码),我们得到这个:

1{ 4}
6{ 9}
11{ 12{ 15}
    19{ 22}
    24{ 26}
    28{ 33}

我们显然缺少一个结束支架.我可以理解scalac猜测丢失的括号可以进入这些地方的任何一个(每个由x表示):

1{ 4}
6{ 9}
11{ x 12{ x 15} x <-- HERE OR HERE OR HERE
      19{ x 22} x <-- OR HERE OR HERE
      24{ x 26} x <-- OR HERE OR HERE
      28{ x 33} x <-- OR HERE OR HERE

但是,这就是scalac的输出结果:

+----- I THINK YOU ARE MISSING A
   |      CLOSING BRACE RIGHT HERE!
1{ V 4}
6{ x 9} 
11{ 12{ 15}
    19{ 22}
    24{ 26}
    28{ 33}

输入的那部分已经很好地嵌套了!怎么可能添加另一个右支撑可能有任何意义?

编辑:我觉得我应该再次重申我的主要问题:你将如何解释这个错误消息(以及如何在源代码中找到错误的根源)给Scala的新手?

解决方法

考虑以下示例(我故意删除了缩进):

case class Foo( i: Int ) {
case class Bar( d: Double ) {
def get = d 
}

它没有编译,但有几个可能正确的代码:

case class Foo( i: Int ) {
}
case class Bar( d: Double ) {
  def get = d 
}

//OR

case class Foo( i: Int ) {
  case class Bar( d: Double ) {
    def get = d 
  }
}

//OR even (still won't compile but the structure is correct so the compiler will proceed with
//another error)

case class Foo( i: Int ) {
  case class Bar( d: Double ) { }
  def get = d 
}

那么编译器应该如何猜测哪个版本是正确的呢?在这种情况下,它选择了第一个有意义的位置:

hello.scala:3: error: Missing closing brace `}' assumed here
def get = d

这对应于第三种选择.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读