The recursion is support by how code execution works. Whenever you make a call to a method this call is pushed into a stack and all other methods called inside this one is pushed on top of the first, only when the method execution finishes the method call is popped from the stack and its return value is available for the outer method that called it to use it.
This way the recursion works because the results of the previous calls are stored in the stack and each call of the method uses the previous value that has already calculated.
The case of tail recursion specifically is that because the recursive call is the last thing done inside the method you don't need to push one call above the other in the stack (that may cause stack overflow exception) because the previous call has already finished. And because of that when you use @tailrec
in scala it converts it to a loop under the hood that is more efficient.
So now I am going to try to answer your questions:
each call to the method has in its accumulator parameter the accumulated value of the factorial so far. The sequence is something like
fact(5, 1)
-> fact(4, 5 * 1)
-> fact(3, 4 * 5 * 1)
-> fact(2, 3 * 4 * 5 * 1)
-> fact(1, 2 * 3 * 4 * 5)
So in the last one call the accum parameter has already the result
- The flow is first you call the
trec
method with the value you want to calculate and then this methods call its internal fact method passing also the value that you want to calculate and the accumulator that in this case is the neutral element in multiplication, 1. And then the flow is the one that I have written in step 1 following the recursion