8

Why doesn't scalac (the Scala compiler) optimize tail recursion?

Code and compiler invocations that demonstrates this:

> cat foo.scala 
class Foo {
 def ifak(n: Int, acc: Int):Int = {  
   if (n == 1) acc  
   else ifak(n-1, n*acc)  
 }
}

> scalac foo.scala
> jd-gui Foo.class
import scala.ScalaObject;

public class Foo
  implements ScalaObject
{
  public int ifak(int n, int acc)
  {
    return ((n == 1) ? acc : 
      ifak(n - 1, n * acc));
  }
}
skaffman
  • 398,947
  • 96
  • 818
  • 769
IttayD
  • 28,271
  • 28
  • 124
  • 178

3 Answers3

12

Methods that can be overridden can NOT be tail recursive. Try this:

class Foo {
  private def ifak(n: Int, acc: Int): Int = {  
    if (n == 1) acc  
    else ifak(n-1, n*acc)  
  }
}
Walter Chang
  • 11,547
  • 2
  • 47
  • 36
  • +1 What's the rationale? ( I mean I can imagine it , but I would like to know ) – OscarRyz Dec 09 '10 at 19:48
  • 2
    @OscarRyz: see http://stackoverflow.com/questions/4785502/why-wont-the-scala-compiler-apply-tail-call-optimization-unless-a-method-is-fina – Seth Tisue Jul 11 '11 at 15:17
1

Try this:

class Foo {
  def ifak(n: Int, acc: Int):Int = {
    if (n == 1) acc
    else ifak(n-1, n*acc)
  }
}

class Bar extends Foo {
  override def ifak(n: Int, acc: Int): Int = {
    println("Bar!")
    super.ifak(n, acc)
  }
}

val foobar = new Bar
foobar.ifak(5, 1)

Notice that ifak may be recursive, but it may not as well. Mark the class or the method final, and it shall probably made tail-recursive.

Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
0

Inner functions are also eligible for TCO.

Randall Schulz
  • 26,420
  • 4
  • 61
  • 81