scala类出错:递归方法printExpr需要结果类型

时间:2012-11-06 22:14:01

标签: scala

我在网上收到错误:

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)
  }
}

3 个答案:

答案 0 :(得分:10)

Scala中的递归方法需要明确声明的返回类型,如错误消息所示。

原因是Scala从方法体中使用的类型推断出方法的返回类型。当方法的返回类型影响方法体中使用的类型(因为它以递归方式调用自身)时,Scala无法确定它应该为方法分配的类型,因此它要求你在源代码中执行此操作(与evalExpr一样,您明确表示它返回Int)。

在这种情况下,您希望printExpr具有返回类型Unit,这是没有信息的无趣值的类型。通常调用返回类型为Unit的方法仅针对其副作用(例如print)。

因此,您可以将printExpr的标题行更改为:

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

或者,Scala有一些用于声明“程序”的语法糖。您可以将“过程”视为不返回任何内容,只是执行一些代码,但实际上Scala中的每个方法都返回某些内容; “procedures”只是返回类型Unit的方法。这样做的语法是在方法的标题之后省略=,但是必须用花括号围绕方法体(即使它是单个表达式,如{{1} }})。所以你可以这样做:

match

避免明确声明def printExpr(e: Expr) { e match { ... } }

答案 1 :(得分:4)

Scala编译无法推断递归方法的类型,因此必须明确声明它:

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

答案 2 :(得分:1)

将回复类型设为printExpr(e : Expr),例如StringExpr,例如

printExpr(e : Expr): Expr
printExpr(e : Expr): String