I thought that the factorial function below is tail-recursive, when I tested it, works fine till 10 and becomes weird at 20 (negative output) and when I insert 100, the answer is 0:
def factorial(n: Int, m: Int = 1): Int =
if (n == 0) m else fact(n-1, m * n)
but when I put @tailrec above it, I get the following error:
error: not found: type tailrec
I can't understand why this function is not tail-recursive. A stack-recursive factorial function is:
def factorial(n: Int): Int =
if (n == 0) 1 else n * factorial(n-1)
The above function modifies the external expression after else at each recursive call. Whereas the first function only modifies what's inside the function. Now, to make a recursive factorial function, what they do is create a function inside a function. But, can a recursive factorial function be created just with the body of the first function in this question?
Also, is the "m" in the former function a variable?
Edit: Now after doing what is suggested in the answer, I get the error message if a function is not tail-recursive:
error: could not optimize @tailrec annotated method factorial: it contains a recursive call not in tail position
Several things:
You have to import @tailrec
annotation to be able to use it without a full name:
import scala.annotation.tailrec
@tailrec
def factorial(n: Int, m: Int = 1): Int =
if (n == 0) m else fact(n-1, m * n)
Without @tailrec
scalac
will still be able to do tail recursion optimization, it just won't enforce it (it won't fail compilation if TRO won't be possible).
Integer has a limited capacity - it's 32-bit 2-compliment and everything bigger than 2^31-1 overflows and goes into negative numbers
So you have to import annotation or use a full name (@scala.annotation.tailrec
) AND replace Int
with something bigger (Long
is also not enough, more like BigInteger
).