12.3 Functions Passed As Parameters

12.3  Functions Passed As Parameters

 In Perl, functions cannot be passed as parameters, but references to functions can. So, if we want to send a function as a parameter, we need to reference it before invoking the function and inside the function’s body, we need to dereference the appropriate elements of the @_ array and then call the function on appropriate actual parameters. A reference to a subprogram can be created in two ways:

    If mysub is a subprogram, a reference to it can be created by writing

 

$mysubRef = \&mysub;

 

  Otherwise, we can write the subprogram without a name and assign this nameless or anonymous subprogram to a scalar that will contain a reference to it.

 

$mysubRef = sub { #subprogram body

                };

 

In the following program, we define a function called find that takes two parameters: a reference to a function and a list of numbers. The first parameter is a reference to a predicate that returns true or false (actually, 1 or 0, in this case). The function find returns those elements of the list that satisfy the predicate whose reference is passed as the first parameter. Here, we have defined two such predicate functions: biggerThan10P which is a named function, and $between10and45P which is actually a reference to a function.

 Program 12.7

#Find those elements of a list that satisfy the condition stated in a 
#function whose reference is passed as the first parameter

#a conditional function or  predicate
sub biggerThan10P{
    if ( $_[0] > 10) {1} else {0}
}

#another conditional function or predicate
$between10and45P = sub {
    if (($_[0] > 10) && ($_[0] < 45)){1} else {0}
}; 


sub find{
    my ($subRef,@lst) = @_;
    my @result;

    foreach $elmt (@lst){
        if (&$subRef($elmt)){
             @result = (@result, $elmt);
            }
    }
    
    return @result;
} 

print join " ", find (\&biggerThan10P, 10, 2, 30, 45, 7), "\n";
print join " ", find ($between10and45P, 10, 2, 30, 45, 7), "\n";

Inside the body of the function find, the first element of @_ is assigned to $subRef which stores the reference to the function supplied as parameter. The function is called by invoking it as &$subRef followed by a list of parameters. When a referenced function is called, the name of the reference scalar must be preceded by the ampersand sign (&).

As mentioned earlier, to obtain the reference to a function, we must precede the function’s name by & if the function is defined with a name. Here, the function biggerThan10P is a regular named function and as a result, a reference to it is obtained by writing \&biggerThan10P. This reference is passed as the first parameter to find in the first call. If a function is defined as a nameless function, a reference to it is obtained by setting a scalar variable. We see an example with the definition of the anonymous function whose reference is stored in the scalar $between10and45P.

We also need to note here that a function that works very similarly to the function find is available as a Perl built-in function. It is called grep. The two calls to find given above can be simulated using grep as the following.

 

grep ($_ > 10, 10, 2, 30, 45, 7)

grep ($_ > 10 && $_ < 45, 10, 2, 30, 45, 7)