6

私はScalaを学んでいるのでg++、からの不可解な出力を読み取るときにコンパイラエラーを思い出すことがよくありscalacます。g++しかし、今日、私は宇宙でさえ起こるとは思えない何かに出くわしました。

友人から、ごくありふれたエラーのある非常に単純なコードスニペットが送られてきました。

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

完全なソースファイルはここに掲載されています。クラス宣言に閉じ中括弧がないためcase class Var、コンパイラーは、その宣言の開始中括弧(11行目)に閉じ中括弧がないことを通知すると思います。ただし、前の宣言scalacの途中で閉じ中括弧が欠落していると「想定」していると報告されています(7行目)。case class(完全なエラー出力は、投稿されたコードの下部に含まれています。)

言語の内部を理解していれば、ほとんどのscalacエラーメッセージは意味がありますが、私はここで完全に途方に暮れています。後のクラス宣言で閉じ中括弧が欠落していると、ファイルの前半ですでに正常に解析されたクラス定義にどのように伝播するのでしょうか。

いったいどうやってこれをScalaの初心者に説明するのですか?閉じ中括弧を外すのは、Scalaを初めて使用する人がよく行う間違いのようなものですが、ここでのエラーメッセージは、代わりにそのようなものを報告する方がおそらくより役立つだろうとユーザーを迷わせるように思われますerror: you seem to be missing a '}' somewhere

注:このような質問に対する通常の回答は、「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の初心者にどのように説明しますか?

4

2 に答える 2

5

次の例を考えてみましょう(意図的にインデントを削除しました)。

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

これは3番目のオプションに対応します。

于 2012-08-21T09:10:59.847 に答える
1

私の質問に対する彼のコメントでのJörgWMittagの提案に続いて、私はScala Issue Trackerで古いチケットを再度開きました:紛らわしい比類のない閉じ中括弧エラー。この質問のコードを、このクラスの紛らわしいエラーメッセージの新しい、短く、再現可能な例として追加しました。

于 2012-10-21T18:29:36.107 に答える