Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error on scala class : recursive method printExpr needs result type

Tags:

scala

I'm getting an error on line :

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

error is :

recursive method printExpr needs result type

This code looks ok to me, what am I doing wrong ?

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)
  }
}
like image 706
blue-sky Avatar asked Nov 06 '12 22:11

blue-sky


3 Answers

Recursive methods in Scala need an explicitly stated return type, as the error message states.

The reason is that Scala infers the method's return type from the types used in the method body. When the method's return type affects the types used in the method body (because it calls itself recursively), Scala isn't able to figure out what type it should assign to the method, so it requires that you do so in the source code (as you have with evalExpr, where you explicitly said that it returns an Int).

In this case, you want printExpr to have return type Unit, which is the type of uninteresting values with no information. Usually calling a method with return type Unit is only done for its side effects (such as print).

So you can change the header line of printExpr to:

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

Alternatively, Scala has some syntactic sugar for declaring "procedures". You can think of a "procedure" as not returning anything, and just executing some code, but really every method in Scala returns something; "procedures" are just methods that return type Unit. The syntax for doing so is to omit the = after the method's header, but then you must surround the method body with curly braces (even if it's a single expression, like your match). So you could do:

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

to avoid explicitly declaring Unit.

like image 129
Ben Avatar answered Nov 14 '22 18:11

Ben


Scala compile cant infer types for recursive methods, so you must declare it explicitly:

def printExpr(e: Expr): Unit = e match {
like image 4
Arjan Avatar answered Nov 14 '22 16:11

Arjan


Give a return type to printExpr(e : Expr) like String or Expr for example

printExpr(e : Expr): Expr
printExpr(e : Expr): String
like image 1
Jeremy D Avatar answered Nov 14 '22 16:11

Jeremy D