This article introduces how to use tail recursion. For more information about tail recursion, see the articles about tail recursion in the next few days. I didn't have much idea about tail recursion before, so I went back and studied tail recursion.
Concept of tail recursion
Tail Recursion is a subset of recursive concepts. For normal recursion, the resulting consumption is immeasurable because we must remember the recursive call stack. For example, in the first example in the section of php below, using php to write a factorial function is caused by recursive stack overflow errors. Tail recursion aims to eliminate the defect of recursive stack loss.
From the code perspective, tail recursion can be clearly defined in one sentence:
The last operation of the function is recursive call.
For example, the Recursive Implementation of php in the "feberatek" series:
The Code is as follows:
Fibonacci. php
Function fibonacci ($ n ){
If ($ n <2 ){
Return $ n;
}
Return maid ($ n-1) + maid ($ n-2 );
}
Var_dump (maid (30 ));
This is a recursive function, but not a tail recursion, because the last operation of fibonacci is an addition operation.
Convert to tail recursion:
The Code is as follows:
Function maid ($ n, $ acc1, $ acc2 ){
If ($ n = 0 ){
Return $ acc1;
}
Return maid ($ n-1, $ acc2, $ acc1 + $ acc2 );
}
Fibonacci2 is a tail recursion. It adds two accumulators, acc1 and acc2, and gives the initial value. Remember: the idea of recursive conversion to tail recursion must be to add accumulators to reduce external recursive operations.
Tail recursion is applied in different languages. Function programming Erlang is the most commonly used function. Almost all recursive functions are modified to tail recursion. The following describes the Performance and Application of tail recursion in several different languages.
Tail recursion in php
Let's make an experiment.
Normal recursion:
The Code is as follows:
Function factorial ($ n)
{
If ($ n = 0 ){
Return 1;
}
Return factorial ($ N-1) * $ n;
}
Var_dump (factorial (100000000 ));
Tail recursion:
The Code is as follows:
Function factorial ($ n, $ acc)
{
If ($ n = 0 ){
Return $ acc;
}
Return factorial ($ n-1, $ acc * $ n );
}
Var_dump (factorial (100000000, 1 ));
Experiment results:
Facts prove that,
Tail recursion does not have any optimization effect in php!
Tail recursion in C
In C, tail recursive optimization is implemented by the gcc compiler. Adding-O2 during gcc compilation will optimize tail recursion.
We can directly view the generated assembly code:
(Use gdb, gcc-O2 factorial. c-o factorial; disass factorial)
Compilation without-O2:
Assembly with O2 optimization:
Don't be too big. I also read the assembly at the beginning, but this code is very simple. I can understand it by searching for commands on the Internet:
The Code is as follows:
Function factoral (n, sum ){
While (n! = 0 ){
Sum = n * sum
N = n-1
}
Return sum
}
Gcc is actually smart optimization.
If you are interested, you can use-O3 to optimize tail recursion and view the Assembly commands.
-The optimization of O3 is to expand the cycle directly.
Summary
The biggest advantage of linear recursive modification to tail recursion is that it reduces the overhead of recursive call stacks. The example of php clearly shows the impact of recursive overhead on the program. However, not all languages Support tail recursion. Even languages that support tail recursion are generally optimized at the compilation stage. For example, the C language in the preceding example optimizes tail recursion. When using tail recursion to optimize code, you must first understand the support of this language for tail recursion.