12.1.2 Functions With Arbitrary Number of “Formal Parameters”
12.1.2 Functions With Arbitrary Number of “Formal Parameters”
Although in the strictest sense, a Perl function has only one single implicit formal parameter of type list, it is possible to simulate a function that takes an arbitrary number of individual formal parameters each of which is scalar. We have put double quotes around the term formal parameters above to indicate that although strictly speaking, we have a single formal parameter, we can think of the single formal parameter to be made up of an arbitrary number of individual formal parameters. When we talk about such individual parameters, we put double quotes around the term.
Thus, in Perl, it is possible to write functions that take an arbitrary number of “formal parameters.” All the parameters are put in a single undifferentiated list and the function is called with this list. This undifferentiated list is a available in a special list variable @_ inside the function. The code inside the function looks at this list variable and retrieves the individual “actual parameters” from this list. Once again, we have put double quotes around the term actual parameters to indicate that these act like several individual actual parameters that are scalar although strictly speaking, it is a single actual parameter that is a list. As a result of this, it is difficult to pass more than one list or hash to the function because it is awkward to indicate where one list or hash ends and the other starts unless we send the lengths of the
lists or hashes as parameters also. If several parameters are passed to a function, it is convenient to send only one list or hash if we do not want to or cannot send the lengths of several lists or hashes. In such a case, it makes sense to send the list or the hash as the last parameter. The first few parameters in such a case are scalars. The text of the function picks out the requisite number of scalars, but treats the rest as a list or a hash. Of course, we can send references to the lists or hashes if we want. A reference is a scalar.
Here is a rewrite of the immediately preceding function. This time, the function has been rewritten to take two parameters.
Program 12.2
use strict;
sub divide {
my $result;
my ($num, $denom) = @_;
if ($denom == 0){
print "You are trying to divide by zero: $num/$denom.\n";
}
else {
$result = $num/$denom;
print "$num/$denom = $result\n";
}
}
#main program
my ($num, $denom);
#first division
$num = 100; $denom = 10;
divide ($num, $denom);
#second division
divide (100, 0);
Here, the function is called divide. It is called with two “actual parameters.” We see two calls to the subprogram in the bottom of the program. In the main program, we create two my variables: $num and $denom. In the body of the subprogram, we create three my variables, $result, $num and $denom. The two variables (viz., $num and $denom) that are common to both the main program and the subprogram are not the same. For example, the $num variables inside and outside the subprogram actually have different memory spaces allocated to them. They are completely distinct. When we refer to $num inside the subprogram, we get the variable local to the subprogram. When the subprogram execution is finished, this variable is no longer available and the variable outside the subprogram becomes visible.
Let us look at the first call:
divide ($num, $denom);
This call to the subprogram provides two “actual parameters” to the function: $num and $denom. However, in reality, the function is called with not two individual “actual parameters,” but a single list that contains the values of the two scalar variables. The value of the resulting list is passed to the function.
So, the function receives an undifferentiated list at initiation. As mentioned earlier, this undifferentiated list is available inside the subprogram as a special variable @_. The code inside the subprogram must look at this variable and then fish out the two scalars that we passed to it. This is done in the expression
my ($num, $denom) = @_;
inside the subprogram. This expression declares two scalar variables with the my declaration making them statically scoped inside the subprogram. In addition, it initializes the two variables by taking the @_ list apart. The first element of @_ becomes the value of $num and the second element of @_ becomes the value of $denom inside the subprogram.
The rest of the subprogram looks at the value of $denom. If $denom is zero, it prints an error message, otherwise, it performs the requested division.
