Reputation: 1608
I have wrtten the following function for pascal triangle. Why the call
pascal_cont(a-1, b-1, (x:Int) => pascal_cont(a, b-1, (y:Int) => cont(x + y)))
is not tail recursive ?
def pascal(c: Int, r: Int): Int = {
def pascal_cont(a:Int, b:Int, cont: (Int) => Int): Int = {
if (a==0 || a==b) cont(1)
else pascal_cont(a-1, b-1, (x:Int) => pascal_cont(a, b-1, (y:Int) => cont(x + y)))
}
pascal_cont(c,r,n => n)
}
Upvotes: 1
Views: 206
Reputation: 14842
The Scala compiler cannot optimize any (theoretically) tail-recursive function, as it translates them to a while-loop. It for example also is unable to optimize mutually tail-recursive functions. You can use the trampoline pattern to mitigate this.
In Scala, scala.util.control.TailCalls
contains the necessary utilities. This will turn into:
def pascal(c: Int, r: Int): Int = {
import scala.util.control.TailCalls._
def pascal_cont(a:Int, b:Int, cont: (Int) => TailRec[Int]): TailRec[Int] = {
if (a==0 || a==b) cont(1)
else tailcall {
pascal_cont(a-1, b-1, (x:Int) =>
pascal_cont(a, b-1, (y:Int) => cont(x + y)))
}
}
pascal_cont(c,r,n => done(n)).result
}
Upvotes: 4
Reputation: 10411
If you add the @tailrec
annotation on the pascal_cont
function you'll get the following error:
[error] ....scala:18: could not optimize @tailrec annotated method pascal_cont: it contains a recursive call not in tail position
[error] pascal_cont(a-1, b-1, (x:Int) => pascal_cont(a, b-1, (y:Int)=> cont (x + y)))
[error] ^
[error] one error found
So the call inside the lambda expression is not in tail position, and that's why it's not tail recursive
Upvotes: 4