Close
Close

Function in Perl


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.

function in Perl

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();
Output
I am a programmer
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.

Notice that we have used { } to represent the body of a function.

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);
Output
even
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);
Output
7
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).

We can also use shift function to extract the first element of the array @_. shift(@array_name) extracts the first element of an array 'array_name' but using only shift will extract the first element of the array @_.
sub is_even{
  $x = shift;
  if ($x%2 == 0){
    print "even\n";
  }
  else{
    print "odd\n";
  }
}
is_even(2);
is_even(3);
Output
even
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";
Output
0
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";
Output
43 6 2 5 3 6 4 2

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;
  }
}
Output

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";
Output
1
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

Notice that we have used my($x). This is necessary because any value of $x will be valid till its block only. It will be different for function 'fac' which is called from one 'fac' function.

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";
Output
Global symbol "$x" requires explicit package name at a.pl line 4.
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.

Examples of series:
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.
0th term of fibonacci series is 0. 1st term of fibonacci series is 1. And its nth term f(n) = f(n-1)+f(n-2)
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";
Output
0
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).


Ask Yours
Post Yours
Doubt? Ask question