Perl | Tail Calls in Function Recursion
Last Updated :
21 Nov, 2019
Recursion in
Perl is any function that does not uses the
for
loop or the
while
loop, instead calls itself during the execution of the program and the corresponding function is known as
recursive function.
Tail recursive function is a special case of recursion in which the function call statement is performed as the final action of the procedure. So
return loop(..);
would work, but
return loop() + operation;
would not.
Tail recursion (or tail-end recursion) is particularly useful, and often easy to handle in implementations. The implementation of tail-recursion is mainly done to avoid the space occupied by stack data structure which keeps track of the data returned from the previous recursion call statement.
Following are few examples for a better understanding of the concept:
Examples 1:
Perl
#!/usr/bin/perl
# Perl Program to calculate Factorial
# Recursion without tail call
sub recurse_fact
{
my $x = $_[0];
# checking if that value is 0 or 1
if ($x == 0 || $x == 1)
{
return 1;
}
# Recursively calling function with
# the next value which is one less
# than current one
else
{
return $x * recurse_fact($x - 1);
}
}
# Recursion using Tail Call
sub tail_recurse_fact
{
my ($ans, $x) = @_;
# checking if that value is 0 or 1
if ($x == 0 || $x == 1)
{
return $ans;
}
# Recursively calling function with
# the next value which is one less
# than current one
else
{
return tail_recurse_fact($ans * $x, $x - 1);
}
}
# Driver Code
$a = 5;
# Function call and printing result after return
print "Factorial of a number $a ",
"through recursion is ", recurse_fact($a);
print "\nFactorial of a number $a ",
"through tail-recursion is ",
tail_recurse_fact(1, $a);
Output:
Factorial of a number 5 through recursion is 120
Factorial of a number 5 through tail-recursion is 120
In the non-tail version, the compiler needs to keep track of the number you're going to multiply it with, whereas in the tail-call version the compiler can realize that the only work left to do is another function call and it can forget about all of the variables and states used in the current function.
Examples 2:
Perl
#!/usr/bin/perl
# Perl program to demonstrate the
# use of tail-recursion
use strict;
use warnings;
sub recurse_fib
{
my $n = shift;
if ($n == 1 or $n == 2)
{
return 1
}
# recursive calling
return (recurse_fib($n - 1) +
recurse_fib($n - 2));
}
sub tail_recurse_fib
{
my ($n, $a, $b) = @_;
if ($n == 1)
{
return $a
}
if ($n == 2)
{
return $b
}
else
{
# tail recursive calling
return tail_recurse_fib($n - 1, $b, $a + $b)
}
}
# Driver code
$a = 10;
print "Fibonacci upto $a through recursion is ",
recurse_fib($a);
print "\nFibonacci upto $a through tail-recursion is ",
tail_recurse_fib($a, 1, 1);
Output:
Fibonacci upto 10 through recursion is 55
Fibonacci upto 10 through tail-recursion is 55
Use of goto
statement to demonstrate Tail Recursion: goto
will transfer the compiler to the subroutine of the given name from the currently running subroutine. This will replace the function call and creates a recursion process in the same way.
Perl
# Perl program to demonstrate the
# use of tail-recursion
use warnings;
sub recurse
{
my $i = shift;
return if $i == 0;
recurse($i - 1);
}
sub tail_recurse
{
my $i = shift;
return if $i == 0;
@_ = ($i - 1);
goto &tail_recurse;
}
# Driver Code
print "recursing\n";
recurse(200);
print "tail_recursing\n";
tail_recurse(200);
Output:
recursing
tail_recursing
In the above example the
recurse
function will produce a fatal error of 'deep recursion' while the
tail_recurse
will work fine.
Elimination of Tail Call
Tail recursive is better than non-tail recursive as tail-recursive can be optimized by modern compilers. What a modern compiler do to optimize the tail recursive code is known as
tail call elimination. Tail call elimination saves stack space. It replaces a function
call with a
goto statement. This really isn't elimination - it is an
optimization.
Sometimes a deeply recursive method is the easiest solution to a problem, but if you recurse more than a couple of hundred calls you'll hit Perl's "deep recursion" error. That is the reason why tail-recursive is used over non-tail recursive codes in Perl.
If we take a closer look at the above-discussed function, we can remove the last call with goto. Below are examples of tail call elimination.
Examples 1: Factorial of a number
Perl
#!/usr/bin/perl
# Perl Program to calculate Factorial
sub tail_recurse_fact
{
my $ans = shift;
my $x = shift;
# checking if that value is 0 or 1
if ($x == 0 || $x == 1)
{
return $ans;
}
# Recursively calling function with
# the next value which is one less
# than current one
else
{
@_ = ($x * $ans, $x - 1);
goto &tail_recurse_fact;
}
}
# Driver Code
$a = 5;
# Function call and printing result after return
print "Factorial of a number $a ",
"through tail-recursion is ",
tail_recurse_fact(1, $a);
Output:
Factorial of a number 5 through tail-recursion is 120
Examples 2: Fibonacci upto n
Perl
#!/usr/bin/perl
# Perl program to demonstrate the
# use of tail-recursion-elimination
use strict;
use warnings;
sub tail_recurse_fib
{
my $n = shift;
my $a = shift;
my $b = shift;
if ($n == 1)
{
return $a
}
if ($n == 2)
{
return $b
}
else
{
@_ = ($n - 1, $b, $a + $b);
# tail recursive calling
goto &tail_recurse_fib;
}
}
# Driver code
$a = 10;
print "Fibonacci upto $a through tail-recursion is ",
tail_recurse_fib($a, 1, 1);
Output:
Fibonacci upto 10 through recursion is 55
Fibonacci upto 10 through tail-recursion is 55
Similar Reads
Function Signature in Perl A Perl function or subroutine is a group of statements that together perform a specific task. In every programming language user want to reuse the code. So the user puts the section of code in function or subroutine so that there will be no need to write code again and again. In Perl, the terms func
5 min read
Perl | return() Function return() function in Perl returns Value at the end of a subroutine, block, or do function. Returned value might be scalar, array, or a hash according to the selected context. Syntax: return Value Returns: a List in Scalar Context Note: If no value is passed to the return function then it returns an
2 min read
Returning Values Functions in LISP In the previous article on the LISP function, we have seen the syntax of defining a function and calling the function by passing some arguments. Returning values from a function: In LISP, whatever is the last expression in the body of a function becomes the return value of that function. Example: Le
2 min read
Recursion in Perl Recursion is a mechanism when a function calls itself again and again till the required condition is met. When the function call statement is written inside the same function then such a function is referred to as a recursive function.The argument passed to a function is retrieved from the default a
3 min read
Tail Recursion in Python Tail recursion is a special case of recursion where the recursive call is the last operation in the function. Therefore, the function returns the result of the recursive call directly, without performing any additional computation after the call. In some languages, tail-recursive functions can be tr
3 min read
Perl | Subroutines or Functions A Perl function or subroutine is a group of statements that together perform a specific task. In every programming language user want to reuse the code. So the user puts the section of code in function or subroutine so that there will be no need to write code again and again. In Perl, the terms func
2 min read
Recursive Functions in R Programming Recursion, in the simplest terms, is a type of looping technique. It exploits the basic working of functions in R. Recursive Function in R: Recursion is when the function calls itself. This forms a loop, where every time the function is called, it calls itself again and again and this technique is
4 min read
What is 'Base Case' in Recursion? Base Case is defined as the condition in Recursive Function, which tells the function when to stop. It is the most important part of every Recursion, because if we fail to include this condition it will result in INFINITE RECURSIONS. In the recursive program, the solution to the base case is provide
4 min read
Recursive Anonymous Function in Golang Recursion is a process in which a function calls itself implicitly or explicitly and the corresponding function is called recursive function. Go language supports special feature called anonymous function. It is a function that doesnât contain any name. It is used to create an inline function. Recur
2 min read
Perl - Closure Function Closure is one of the important concepts in Perl. Closure is a computer term with an accurate but a hard to explain meaning. It is often referred as a function that can be stored as a variable, which has a special ability to access other variables local to the scope it was created in. It is used to
5 min read