We have already used different functions but in this section we are going to make our own functions.
Why do we need functions?
Function or subroutine or method is a set of codes written together in our program and given a name. We can call that set of program at any place of our code by just calling its name and without writing the whole set of codes again.

Let's take an example.
sub print_poem{
print "I am a programmer
You have a hammer
I like code
and I hate load\n";
}
print_poem();
You have a hammer
I like code
and I hate load
sub is a keyword used for making functions. We first write sub and then the name of the function to make a function.
print_poem is the name of the function. It means that we can use all the codes written inside it by just using this name.
print_poem(); - Here we have called the print_poem function and then the codes inside it got executed.
Passing arguments to function
We can also pass arguments to a function while calling it. It means that we can pass a value to a function while calling it. Passed arguments are stored inside a function in an array @_. It means that whatever you have passed, it will be stored in this array (@_) and to access them, we need to access the elements of this array. We can access the 1st passed argument as $_[0], 2nd passed argument as $_[1] and so on.
Suppose you have written a function to check if a number is even or not, then you can pass different numbers while calling the function to check. It will be clear by the example given below:
sub is_even{
$x = $_[0];
if ($x%2 == 0){
print "even\n";
}
else{
print "odd\n";
}
}
is_even(2);
is_even(3);
odd
is_even is the name of the function.
$x = $_[0] - Our first passed parameter will be $_[0] in function.
2 is passed in the first function call. In the function, $_[0] is 2 (as we have passed 2).
In the same way, during second time, 3 is passed. So, $_[0] is 3 there.
Once a function is called, codes inside the function are executed. So, when is_even(2) was called, then the codes inside the function 'is_even' were executed with '$_[0]=2'.
As we saw here, we have not passed any parameter. Whenever we want to print the whole poem, we just have to call that function.
Let's see one more example for calculating the sum of the numbers passed to the function:
sub sum{
$s = 0;
foreach $i (@_){
$s = $s + $i;
}
print "$s\n";
}
sum(2,5);
sum(5,2,3);
10
In the above example, we are accessing every element of our function sum using array @_. So, when we called 'sum(2,5)', @_ became (2,5) and when we called 'sum(5,2,3)', @_ became (5,2,3).
sub is_even{
$x = shift;
if ($x%2 == 0){
print "even\n";
}
else{
print "odd\n";
}
}
is_even(2);
is_even(3);
odd
Returning from a function
Functions can do one more thing, they can return you something. This means that these can give you something back. This will be clearer from the following examples. Let's see how:
sub is_even{
$x = $_[0];
if ($x%2 == 0){
return 1;
}
else{
return 0;
}
}
print is_even(1),"\n";
print is_even(2),"\n";
1
Here, our function is returning us a number (0 or 1). So, after 1 is returned from 'is_even(2)', the statement print is_even(2),"\n"; became equivalent to print 1,"\n";. Let's see one more example.
sub rev{
@c = ();
$i = scalar@_-1;
while ($i>=0){
push(@c,$_[$i]);
$i = $i-1;
}
return @c;
}
@z = rev(2,4,6,3,5,2,6,43);
print "@z\n";
Here, our function is returning an array.
Calling a function inside another function
Yes, we can call a function inside another function.
Let's take an example of checking a number's divisibility with 6. For a number to be divisible by 6, it must be divisible by both 2 and 3. In the example given below, we have a function is_even to check its divisibility with 2. div6 function calls the is_even inside itself to check the number's divisibility with both 2 and 3. Let's see how:
sub is_even{
$x = $_[0];
if ($x%2 == 0){
return 1;
}
else{
return 0;
}
}
# div6 function to check divisiblity by 6
sub div6{
$y = $_[0];
if (is_even($y) && $y%3 == 0){
return 1;
}
else{
return 0;
}
}
We have called is_even function inside div6 function.
Here, is_even will return 1 if the given number is even or divisible by 2. And if (is_even($y) and $y%3 == 0) will be true only if is_even and $y%3==0 both are true, which means that the number is divisible by both 2 and 3 or divisible by 6.
Recursion
Recursion is calling a function inside the same function. Before going into this, let's learn some mathematics.
We will calculate the factorial of a number. Factorial of any number n is (n)*(n-1)*(n-2)*....*1 and written as (n!) and read as 'n factorial'.
e.g.:
4! = 4*3*2*1 = 24
3! = 3*2*1 = 6
2! = 2*1 = 2
1! = 1
Also, 0! = 0
Let's code to calculate the factorial of a number:
sub fac{
my($x) = $_[0];
if ($x == 0 || $x == 1){
return 1;
}
else{
return $x*fac($x-1);
}
}
print fac(0),"\n";
print fac(1),"\n";
print fac(4),"\n";
print fac(5),"\n";
print fac(10),"\n";
1
24
120
3628800
Let's go through this code.
If we give 0 or 1, our function will return 1 because the vaue of both 0! and 1! are 1. It is very simple till here. Now see what happens if we pass 2 to our function 'fac'
else{
return x*fac(x-1)
}
Going for fac(x-1) i.e. fac(1) which is 1. ( This is called recursion, the fac function is called inside itself ). So, it is 2*factorial(1) = 2*1 i.e. 2.
So, it will return 2.
Now see for 3:
x*factorial(x-1)
3*factorial(2) Now fac(2) will be called and then it will be 2*fac(1):
3*2*fac(2) Since, fac(2) will be 2*fac(2-1)
3*2*1
So, it will return 6.
For 4
4*fac(3)
4*3*fac(2)
4*3*2*fac(1)
4*3*2*1
You have just done something which most beginners have a tough time doing. Go and get yourself a cookie.
use warnings and use strict
use strict is used to make sure that all the variables are declared with my. It minimizes the number of errors. We write use strict; at the beginning of our program to use this.
use warnings is used to emit warnings if we are doing wrong things. We declare it also at the top of our program by writing use warnings;.
Let's write the above code using these two and without my and see what happens.
use strict;
use warnings;
sub fac{
$x = $_[0];
if ($x == 0 || $x == 1){
return 1;
}
else{
return $x*fac($x-1);
}
}
print fac(0),"\n";
print fac(1),"\n";
print fac(4),"\n";
print fac(5),"\n";
print fac(10),"\n";
Global symbol "$x" requires explicit package name at a.pl line 5.
Global symbol "$x" requires explicit package name at a.pl line 5.
Global symbol "$x" requires explicit package name at a.pl line 9.
Global symbol "$x" requires explicit package name at a.pl line 9.
Execution of a.pl aborted due to compilation errors.
Do you know Fibonacci series?
It is a series having its 0th and 1st terms 0 and 1 respectively.
2,4,6,8,10,... is a series. Its nth term is n*2. Eg- 1st term is 2*1 = 2, 2nd term is 2*2 = 4.
One more example can be 11,15,19,23,... . Its 1st term is 11 and any other nth term is (n-1)th term + 4. Eg- 2nd term is 1st term + 4 = 11+4 = 15. 3rd term is 2nd term + 4 = 15+4 = 19.
It means that
f(2) = f(1)+f(0)
= 1+0 = 1
f(3) = f(2)+f(1)
= 1 + 1 = 2
Now, let's program it
use strict;
use warnings;
my %prev = (0=>0,1=>1);
sub fib{
my($n) = $_[0];
if (exists($prev{$n})){
return $prev{$n};
}
else{
my($fi);
$fi = fib($n-1) + fib($n-2);
$prev{$n} = $fi;
return $fi;
}
}
print fib(0),"\n";
print fib(1),"\n";
print fib(2),"\n";
print fib(3),"\n";
print fib(4),"\n";
1
1
2
3
%prev = (0=>0,1=>1) - We are using a hash to store the Fibonacci series corresponding to the nth term. Initially there are only two numbers f(0) = 0 and f(1) = 1.
Coming to the next line:
if (exists($prev{$n})) If the required term is in the hash, then it will simply return that, else it will calculate and also store the corresponding calculated value in the hash.
For f(2):
$fi = fib(n-1) + fib(n-2) => $fi = f(1)+f(0) = 1.
$prev($n) = $fi It will update our hash and return 1 in the last line.
For f(3)
$fi = f(1)+f(2)
For f(1), simply 1 will be returned and f(2) will be calculated as shown above and thus 1+0 i.e., 1 will be returned.
Similarly we will do for f(4).