Perl | References to a Subroutine

Prerequisite: Perl references

Declaring References to a Subroutine

In Perl, a reference is, exactly as the name suggests, a reference or pointer to another object. References actually provide all sorts of abilities and facilities that would not otherwise be available and can be used to create sophisticated structures such as Dispatch tables, Higher-order procedures, Closures, etc. For C programmers using Perl for the first time, a reference is exactly like a pointer, except within Perl it’s easier to use and, more to the point, more practical. There are two types of references: symbolic and hard.

Symbolic reference enables you to use the value of another variable as a reference to a variable by name. For example, if the variable $val contains the string "Text", the symbolic reference to $val refers to the variable $Text.
A hard reference is a term for actual data that is contained in a data structure. However, the form of the data structure to which it points is largely irrelevant. Although a hard reference can refer to a single scalar, it can also refer to an array of scalars, a hash, or a subroutine.



$val = "Text";
$val_ref = \$val;

# For other variables
$array = \@ARGV;
$hash = \%ENV;

# For reference to subroutine
sub val { print "val" };
$valsub = \&val;

Calling a subroutine Reference

Calling a subroutine reference is also known as dereferencing. It is the act of extracting information from the structures. When you dereference a scalar reference, you are in fact referring to the original data structure. The most direct approach of dereferencing a reference is to prepend the relevant data type character ($ for scalars, @ for arrays, % for hashes, and & for subroutines) that you simply expect before of the scalar variable containing the reference.

$val_ref = \$val;       # Create reference to scalar
$array = \@ARGV;        # Create reference to array
$hash = \%ENV;          # Create reference to hash
$valsub = \&            # Create reference to subroutine

# Dereferencing
$$val_ref;
$$array[0, 1, ....];
$$hash{'...'};
&$valsub;

Note: The act of dereferencing information must be explicit. There is no implicit dereferencing supported within Perl on any structure.

Subroutines can be both named as well as anonymous. Perl provides the facility to declare references to both the types of subroutines and to dereference them.

Example 1:

filter_none

edit
close

play_arrow

link
brightness_4
code

#!/usr/bin/perl
  
# Perl program to demonstrate
# reference to subroutines
  
# Creating a named subroutine
sub name
{
    return "GeeksforGeeks";
}
  
# Create callable reference 
# to named subroutine
$rs1 = \&name;     
print("Reference to named subroutine: ", $rs1);
print("\nAfter deferencing, value : ", &$rs1); 
  
# Create a reference to an 
# anonymous subroutine
$rs2 = sub{
               return "GFG";
          }; 
print("\n");
print("\nReference to anonymous subroutine: ", $rs2);
print("\nAfter deferencing, value : ", &$rs2); 

chevron_right


Output:

Reference to named subroutine: CODE(0x25f7750)
After deferencing, value : GeeksforGeeks

Reference to anonymous subroutine: CODE(0x25f7870)
After deferencing, value : GFG

The use of infix operation is shown in the below example. The infix operation provides a better and easier way of extracting information from the complex or nested structures.

Example 2:

filter_none

edit
close

play_arrow

link
brightness_4
code

#!/usr/bin/perl
  
# Perl program to demonstrate
# reference to subroutines
  
$rs = \&func1;
  
# Prints "GeeksforGeeks"
$rs->("Geeks")->("for")->("Geeks");     
  
sub func1
{
    my $val = shift;
    print "$val";
    return \&func2;
}
  
sub func2
{
    my $val = shift;
    print "$val";
    return \&func3;
  
sub func3 
{
    my $val = shift;
    print "$val\n";
}

chevron_right


Output:

GeeksforGeeks

Callbacks

Callbacks is one of the important element that one should remember when developing Perl Tk interfaces. It calls back a piece of code from another part of the script when we reach a certain point of condition or perform a certain action.
Callbacks are somewhat like a delayed execution of code, which is triggered by an event instead of executing things in a linear way. For such event-driven functionality of code, we often make use of subroutine references to call such pieces of code when required.

Example:


filter_none

edit
close

play_arrow

link
brightness_4
code

# Perl program to demonstrate 
# the use of callbacks
sub alt {
            print "$a $b\n";
            $arr{$a} cmp $arr{$b};
        }
  
%arr = ("Marcelo", "Lewis",
        "Rodrygo", "Peter",
        "Sandro", "James");
  
# @names = sort alt (keys(%arr));
@names = calc ("Alternate", keys(%arr));
foreach $person (@names
{
    print "$person teams up with $arr{$person}\n";
}
  
# Example code to show 
# what really goes on inside sort.
sub calc 
{
    my ($subn, @final) = @_;
    for ($k = 0; $k < $final; $k++) 
    {
        $count = 0;
        for ($j = 0; $j < $final - $k; $j++) 
        {
            $a = $final[$j];
            $b = $final[$j + 1];
            if (&{$subn}() > 0 )
            {
                $final[$j] = $b;
                $final[$j + 1] = $a;
                $count++;
            }
        }
        last unless ($count);
    }
    return @final
}

chevron_right


Output:

Sandro teams up with James
Rodrygo teams up with Peter
Marcelo teams up with Lewis

The above example depicts the sorting of a list of hash keys based on the number of characters (length) in the value held in the hash using a callback function calc.

Arrays and Hashes of References

Beyond the normal constraints of arrays and hashes, you can also create complex structures made up of combinations of the two. These are nested, or complex structures and they can be used to model complex data in an easy-to-use format. What actually happens with a nested structure is that Perl stores the nested data type as a reference to an anonymous variable. For example, in a two-dimensional array, the main array is a list of references, and the sub-arrays are anonymous arrays to which these references point. This means that an “array of arrays” actually means an array of references to arrays. The same is true for all nested structures; and, although it seems complex, it does provide a suitably powerful method for creating complex, nested structures.

Example 1:

filter_none

edit
close

play_arrow

link
brightness_4
code

w
# Perl program to demonstrate
# array of references
  
# Declaring a reference to a nested array
$array = [[1, 2, 3, 4, 5], 
          ['Geeks', 'for', 'Geeks'], 
          [6, 7, 8, 9]];
  
# Access element using index
# Dereferencing performed
print("$$array[1][2]");     
  
# Access element using infix method
print("\n$array->[1][1]");
print("\n$array->[1]->[0]");
  
# Printing complete nested array
print("\nElements in the array are :");
print("\n");
for(my $i = 0; $i < scalar(@{$array}); $i++)
{
    for(my $j = 0;  
           $j < scalar(@{$array->[$i]}); $j++)
    {
        print($$array[$i][$j]);
        print(" ");
    }
    print("\n");
}

chevron_right


Output:

Geeks
for
Geeks
Elements in the array are :
1 2 3 4 5 
Geeks for Geeks 
6 7 8 9

Example 2:

filter_none

edit
close

play_arrow

link
brightness_4
code

#!/usr/bin/perl
  
# Perl program to demonstrate
# array of references
use strict;
use warnings;
  
my %friends = ( 1 => 'John',     4 => 'Sandro',
                2 => 'Rodrygo', 5 => 'Peter',
                3 => 'Marcelo', 6 => 'Luis' );
  
# Declaring a Reference to the hash
my $hash_ref = \%friends;
  
# Access element from hash using key value
print("$$hash_ref{1}\n");     # prints John
  
# Acces element using infix operation
print("$hash_ref->{3}\n");
  
# Print all elements of the hash
# with their keys
print ("The hash stored is :\n");
  
for (keys %$hash_ref)
{
    print("$_ = $hash_ref->{$_}\n");
}

chevron_right


Output:

John
Marcelo
The hash stored is :
4 = Sandro
1 = John
2 = Rodrygo
5 = Peter
3 = Marcelo
6 = Luis


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.




Article Tags :
Practice Tags :


Be the First to upvote.


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.