我在网上收到错误:
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)
}
}
答案 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)
,例如String
或Expr
,例如
printExpr(e : Expr): Expr
printExpr(e : Expr): String