In Perl, references are not just pointers, they are data types.
Creating a Reference
When a reference is declared, a new instance of the reference is created and stored in a scalar.
# Set up the data types.
my $scalarVar = "Something";
# Create a reference to it.
my $scalarRef = \$scalarVar;
Dereferencing a Reference
In order to access the information that a reference points to, the reference must be dereferenced. Perl's references do not automatically dereference themselves when used. e.g.
# Initialize variables
my $scalarVar = "something";
my @arrayVar = qw(a b c d e);
my %hashVar = ("Toronto" => "East", "Calgary" => "Central", "Vancouver" => "West");
# Create the references
my $scalarRef = \$scalarVar;
my $arrayRef = \@arrayVar;
my $hashRef = \%hashVar;
# Print out the references.
print "$scalarRef \n";
print "$arrayRef \n";
print "$hashRef \n";
# The output of the program is
SCALAR(0xaddc4)
ARRAY(0xadec0)
HASH(0xade30)
So, how do we dereference? Dereferencing is different for scalar, array, etc. Lets look at each one of them.
Scalar References
A scalar reference is reference to a scalar value. The example below show how a scalar reference is created, dereferenced, and printed.
# Creating a scalar variable
my $scalarVar = "something";
# Creating a scalar reference
my $scalarRef = \$scalarVar;
# Printing a scalar variable
print "Var: $scalarVar \n";
# Printing a scalar reference
print "Ref: " . $$scalarRef . "\n";
# The output would be
Var : something
Ref: something
Note the two $ signs in the scalar reference. Also note the difference in the way the scalar variable and scalar reference is printed.
Array References:
Array reference is created using \ operator and dereferenced using @$.
# Create the array
my @letters = qw(a b c d e);
# Create the array reference
my $arrayRef = \@letters;
# Printing the array reference
for $month (@$arrayRef)
{
print "Letters: $letter \n";
}
Hash References:
Hash references are created using \ operator and dereferenced using %$.
# Create and associative array
my %who = ('Name' => 'Gizmo', 'Age' => 3, 'Height' => '10 cm', 'Weight' => '10 gm');
# Create the hash reference
my $hashRef = %who;
# Print the associative array
for $key (sort keys %$hashRef)
{
$value = $hashRef->{$key};
printf "Key: %10s Value: %-40s\n", $key, $value;
}
# output of program
Key: Age Value: 3
Key: Height Value: 10 cm
Key: Name Value: Gizmo
Key: Weight Value: 10 gm
Code References
A code reference points to a Perl subroutine. Code references are mainly used for callback functions, where a callback is a function that you ask to have called at a later time. Code references are created with \ operator and dereferenced with &$.
# define the callback function
sub callBack
{
my ($mesg) = @_;
print "$mesg\n";
}
# Create the code reference
my $codeRef = \&callBack;
# Call the callback function with different parameters.
&$codeRef("Hi someone");
&$codeRef("something");
Anonymous Array References
An anonymous array is an array without an associated name variable. This means the array has been defined and stored into a reference instead of an array variable. There will be times when you may want to create a temporary array but don't feel like creating a new array name. When you use an anonymous array, Perl creates the namespace for the array. To create an anonymous array, use square brackets around a list of values. The following is an anonymous array inside an anonymous array.
# create the anonymous array reference
My $arrayRef = [[1, 2, 3, 4], 'a', 'b', 'c', 'd', 'e', 'f'];
# Print out some of the array
print $arrayRef->[0][0] . "\n";
print $arrayRef->[0][1] . "\n";
print $arrayRef->[1] . "\n";
# output is
1
2
a
References are particularly useful in creating multidimensional data structures. As we saw earlier, nested lists are automatically flattened, so trying to build a list of lists doesn't work:
@table = (
( 1, 2, 3 ),
( 2, 4, 6 ),
( 3, 6, 9 ),
);
This fails to have the desired effect because flattening makes the above equivalent to:
@table = (1,2,3,2,4,6,3,6,9);
Fortunately, each element in a Perl array can store any kind of scalar value. Since a reference is just a special kind of scalar, it's possible to write:
@row1 = (1,2,3);
@row2 = (2,4,6);
@row3 = (3,6,9);
@cols = (\@row1, \@row2, \@row3);
$table = \@cols;
Now the elements in the "row" arrays can be accessed using the arrow notation:
print "2 x 3 is ", $table->[1]->[2];
Of course, tables like this are very popular, so Perl provides syntactic assistance. If we specify a list of values in square brackets instead of parentheses, the result is not a list, but a reference to a nameless (or anonymous) array. That array is automatically initialized to the specified values. So the above code could be written as:
$row1_ref = [ 1, 2, 3];
$row2_ref = [ 2, 4, 6];
$row3_ref = [ 3, 6, 9];
$table = [$row1_ref, $row_ref, $row3_ref];
or use nested brackets
my $table =
[
[ 1, 2, 3],
[ 2, 4, 6],
[ 3, 6, 9],
]
And finally
print $table->[1]->[2];
can be replaced with
print $table->[1][2];
Anonymous Hash References
Anonymous hash or associative array references are created the same way anonymous array references are created. The hash is created and the reference is stored directly into the reference.
my $hashRef = {'Name' => 'Gizmo', 'Age' => 3, 'Height' => '10 cm'};
print $hashRef->{'Name'} . "\n";
print $hashRef->{'Age'} . "\n";
print $hashRef->{'Height'} . "\n";
# output is
Gizmo
3
10 cm
It is possible to create references to anonymous hashes by replacing the parentheses of a hash-like list:
%association = ( cat=>"nap", dog=>"gone", mouse=>"ball" ); # parentheses
with curly braces:
$association = { cat=>"nap", dog=>"gone", mouse=>"ball" }; # curly braces
Like the [...] array constructor, the {...} hash constructor returns a reference, which must be assigned to scalar variable ($association), not to a hash (%association). Access to the resulting anonymous hash is only possible through the returned reference:
print $association->{cat};
We can even create multilevel hashes, by nesting anonymous hash references:
$behaviour =
{
cat => { nap => "lap", eat => "meat" },
dog => { prowl => "growl", pool => "drool" },
mouse => { nibble => "kibble" },
};
Accessing the data requires a chain of arrow operators:
print $behaviour->{cat}->{eat};
And, as with multidimensional arrays, any arrows after the first can be omitted:
print $behaviour->{mouse}{nibble};
Anonymous Subroutine References
An anonymous subroutine is a subroutine that has been defined without a name. The $ operator is used to access the anonymous routine. The following script creates a reference to an anonymous function.
my $codeRef = sub { my $mesg = shift; print "mesg\n"; };
&$codeRef ("hi someone");
&$codeRef("something");
Passing subroutine arguments as explicit references
References also provide a means of passing unflattened arrays or hashes into subroutines. Suppose we want to pass array of values to a subroutine. We can't call this subroutine in the obvious way:
insert(@ordered, $next_val);
because normal list flattening will squash the contents of @ordered and the value of $next_val into a single list. Instead, we could set up the subroutine insert so that it expected a reference to the array as its first argument:
sub insert
{
($arr_ref, $new_val) = @_;
@($arr_ref) = sort {$a<=>$b} (@{$arr_ref}, $new_val); # numerical sort
}
We could then call it like so:
insert(\@ordered, $next_val);
Identifying a Referent
Because a scalar variable can store a reference to any kind of data, and dereferencing a reference with the wrong prefix leads to fatal errors, it's sometimes convenient to be able to determine the type of referent to which a specific reference refers. Perl provides a built-in function called ref that takes a scalar, such as $$slr_ref, and returns a description of the kind of reference it contains.
What ref returns If $slr_ref contain ... then ref($slr_ref) returns ...
a scalar value undef
a reference to a scalar "SCALAR"
a reference to an array "ARRAY"
a reference to a hash "HASH"
a reference to a subroutine "CODE"
a reference to a filehandle "IO" or "IO::Handle"
a reference to a typeglob "GLOB"
a reference to a precompiled pattern "Regexp"
a reference to another reference "REF"
The ref function can be used to improve error messages.
die "Expected scalar reference" unless ref($slr_ref) eq "SCALAR";
or to allow a subroutine to automatically dereference any arguments that might be references:
sub trace
{
($prefix, @args) = @_;
foreach $arg ( @args );
{
if (ref($arg) eq 'SCALAR') { print $prefix , ${$arg} }
elsif (ref($arg) eq 'ARRAY') { print $prefix, @{$arg} }
elsif (ref($arg) eq 'HASH') { print $prefix, $arg }
else { print $prefix, $arg }
}
}
The ref function has a vital additional role in object-oriented Perl, where it can be used to identify the class to which a particular object belongs.