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:
perl
#!/usr/bin/perl # Perl program to demonstrate # reference to subroutines # Creating a named subroutine sub name { return "w3wiki" ; } # Create callable reference # to named subroutine $rs1 = \&name; print ( "Reference to named subroutine: " , $rs1 ); print ( "\nAfter dereferencing, value : " , & $rs1 ); # Create a reference to an # anonymous subroutine $rs2 = sub { return "GFG" ; }; print ( "\n" ); print ( "\nReference to anonymous subroutine: " , $rs2 ); print ( "\nAfter dereferencing, value : " , & $rs2 ); |
Reference to named subroutine: CODE(0x981750) After dereferencing, value : w3wiki Reference to anonymous subroutine: CODE(0x981870) After dereferencing, 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:
perl
#!/usr/bin/perl # Perl program to demonstrate # reference to subroutines $rs = \&func1; # Prints "w3wiki" $rs ->( "Beginner" )->( "for" )->( "Beginner" ); 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" ; } |
w3wiki
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:
Perl
# 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 } |
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:
perl
w # Perl program to demonstrate # array of references # Declaring a reference to a nested array $array = [[1, 2, 3, 4, 5], [ 'Beginner' , 'for' , 'Beginner' ], [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" ); } |
Beginner for Beginner Elements in the array are : 1 2 3 4 5 Beginner for Beginner 6 7 8 9
Example 2:
perl
#!/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 # Access 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" ); } |
John Marcelo The hash stored is : 4 = Sandro 1 = John 2 = Rodrygo 5 = Peter 3 = Marcelo 6 = Luis