Reputation:
I come from a object oriented background, where I primarily wrote applications in Java. I recently started to explore more on Scala and I have been reading some text. I thus came across something called tail recursion. I understood how to write tail recursive methods.
For example - To add the elements in a List (Of course this could be done using reduce method) but for the sake of understanding, I wrote a tail recursive method:
@scala.annotation.tailrec
def sum(l: List[Int], acc: Int): Int = l match {
case Nil => acc
case x :: xs => sum(xs, acc + x)
}
How is this recursion handled internally by the Scala run time?
Upvotes: 0
Views: 283
Reputation: 369430
How is this recursion handled internally by the Scala run time?
It isn't. It is handled by the compiler at compile time.
Tail-recursion is equivalent to a while
loop. So, a tail-recursive method can be compiled to a while
loop, or, more precisely, it can be compiled the same way a while
loop is compiled. Of course, how exactly it is compiled depends on the compiler being used.
There are currently three major implementations of Scala, these are Scala-native (a compiler that targets native machine code with its own runtime), Scala.js (a compiler that targets the ECMAScript platform, sitting on top of the ECMAScript runtime), and the JVM implementation Scala which confusingly is also called "Scala" like the language (which targets the JVM platform and uses the JVM runtime). There used to be a Scala.NET, but that is no longer actively maintained.
I will focus on Scala-JVM in this answer.
I'll use a slightly different example than yours, because the encoding of pattern matching is actually fairly complex. Let's start with the simplest possible tail-recursive function there is:
def foo(): Unit = foo()
This gets compiled by Scala-JVM to the following JVM bytecode:
public void foo()
0: goto 0
Remember how I said above that tail-recursion is equivalent to looping? Well, the JVM doesn't have loops, it only has GOTO
. This is exactly the same as a while
loop:
def bar(): Unit = while (true) {}
Gets compiled to:
public void bar()
0: goto 0
And for a slightly more interesting example:
def baz(n: Int): Int = if (n <= 0) n else baz(n-1)
gets compiled to:
public int baz(int);
0: iload_1
1: iconst_0
2: if_icmpgt 9
5: iload_1
6: goto 16
9: iload_1
10: iconst_1
11: isub
12: istore_1
13: goto 0
16: ireturn
As you can see, it is just a while
loop.
Upvotes: 3