7

オンラインでエラーが発生します:

case Sum(l, r) => printExpr(l); print("+"); printExpr(r)

エラーは:

再帰メソッド printExpr には結果の型が必要です

このコードは私には問題ないように見えますが、何が間違っていますか?

abstract class Expr {

  case class Num(n: Int) extends Expr
  case class Sum(l: Expr , r: Expr) extends Expr
  case class Prod(l: Expr, r: Expr) extends Expr

  def evalExpr(e: Expr): Int = e match {
    case Num(n) => n
    case Sum(l, r) => evalExpr(l) + evalExpr(r)
    case Prod(l, r) => evalExpr(l) * evalExpr(r)
  }

  def printExpr(e: Expr) = e match {
    case Num(n) => print(" " + n + " ")
    case Sum(l, r) => printExpr(l); print("+"); printExpr(r)
    case Prod(l, r) => printExpr(l); print("x"); printExpr(r)
  }
}
4

3 に答える 3

12

エラー メッセージに示されているように、Scala の再帰メソッドには、明示的に指定された戻り値の型が必要です。

その理由は、Scala がメソッド本体で使用される型からメソッドの戻り値の型を推測するためです。メソッドの戻り値の型がメソッド本体で使用される型に影響する場合 (メソッド自体が再帰的に呼び出されるため)、Scala はメソッドに割り当てるべき型を判断できないため、ソース コードでそれを行う必要があります (あなたが持っているようにevalExpr、あなたはそれが を返すと明示的に言ったInt)。

この場合、printExpr戻り値の型が必要ですUnit。これは、情報を持たない興味深い値の型です。通常、戻り値の型を持つメソッドの呼び出しはUnit、その副作用 ( などprint) のためにのみ行われます。

したがって、ヘッダー行を次のように変更できますprintExpr

def printExpr(e: Expr) : Unit = e match {

あるいは、Scala には「手続き」を宣言するための構文糖衣があります。「プロシージャ」は何も返さず、コードを実行するだけだと考えることができますが、実際には Scala のすべてのメソッドは何かを返します。「プロシージャ」は、 type を返す単なるメソッドですUnit。これを行うための構文は=、メソッドのヘッダーの後にある を省略しますが、メソッド本体を中かっこで囲む必要matchがあります ( のように単一の式であっても)。したがって、次のことができます。

def printExpr(e: Expr) {
  e match {
    ...
  }
}

を明示的に宣言しないようにしUnitます。

于 2012-11-06T22:20:23.173 に答える
4

Scala コンパイルでは再帰メソッドの型を推測できないため、明示的に宣言する必要があります。

def printExpr(e: Expr): Unit = e match {
于 2012-11-06T22:21:13.763 に答える
1

printExpr(e : Expr)likeに戻り値の型を指定するStringExpr、たとえば

printExpr(e : Expr): Expr
printExpr(e : Expr): String
于 2012-11-06T22:21:07.693 に答える