2. Scalar: reference

You can easily find confusing definitions of a Perl reference. Let's avoid this now!

  • A reference is a scalar variable
  • that refers to another variable (the so called referent), like -amongst others- a scalar, array, hash and a function
  • and enables complex and compound data structures (nested arrays, hashes, scalars and more)
and

  • A reference contains information about the location of the referent and the referent type.
and finally

  • You can use a reference anywhere you would use a scalar, except as key of a hash!
  • Any Perl data type can have a reference.
  • References saves memory: they make multiple copies of the same variable unnecessary.

2.1 Scalar references

A scalar reference is a reference to a scalar:
$name = "Reinier";
print("$name\n"); # output: Reinier
$ref = \$name; # creates the reference, with a backslash before the scalar sigil $
print("$ref\n"); # output: SCALAR(0x55f3f15dd200), an internal Perl key, that looks like a memory adress
print("$$ref\n"); # output: Reinier. Notice the extra $, i.e. the so called dereferencing operator
$$ref = "Barbara"; # change $name indirectly
print("$name\n"); # output: Barbara
Scalar references are not very common.

2.2 Array references

An array reference is a reference to an array:
@kids = qw (Sebastian Daniel Florence);
$aref = \@kids; # creates the reference, with a backslash before the array sigil @
print("$aref\n"); # output: ARRAY(0x556bc9248300), an internal Perl key, that looks like a memory adress
print "@{$aref}\n"; # output: Sebastian Daniel Florence. Notice the @, i.e. the so called dereferencing operator
print "$aref->[1]\n"; # output: Daniel
print "$$aref[1]\n"; # output: Daniel
print "$$aref[2]\n"; # output: Florence
print "$$aref[-1]\n"; # output: Florence
2.2.1 Passing array references as arguments
Array references are very useful in passing arguments to a subroutine. Let's first pass arrays directly.
sub length_passed_array_without_ref {
$res = 0;
print "@_\n"; # output: 1, 2, 3, 4, 5, 7, 8, 9, i.e. the two arrays are flattened into a long list
$res = scalar(@_);
return ($res);
}

@list1 = (1, 2, 3);
@list2 = (4, 5, 7, 8, 9);
$result = length_passed_array_without_ref(@list1, @list2);
print("$result\n"); # output: 8
If you want the length of both arrays separately, i.e. avoid flattening of the passed arrays, you've to use references:
sub length_passed_arrays_with_ref {
@res = ();
foreach $arg (@_) { # $arg contains the passed references
push(@res, scalar(@$arg)); # dereferencing $arg and 'casting' to a scalar context -> length array
}
return (@res);}

@list1 = (1, 2, 3);
@list2 = (4, 5, 7, 8, 9);
@result = length_passed_arrays_with_ref(\@list1, \@list2);
print("@result\n"); # returns 3 5
A bit more concise
sub length_passed_arrays_with_ref {
@res = ();
push(@res, scalar(@$_)) foreach (@_);
return (@res);}

@list1 = (1, 2, 3);
@list2 = (4, 5, 7, 8, 9);
@result = length_passed_arrays_with_ref(\@list1, \@list2);
print("@result\n"); # returns 3 5
and more efficient (see Chapter 3.8 below)
sub length_passed_arrays_with_ref {
my @res = ();
push(@res, scalar(@$_)) foreach (@_);
return (\@res);}

@list1 = (1, 2, 3);
@list2 = (4, 5, 7, 8, 9);
$result = length_passed_arrays_with_ref(\@list1, \@list2);
print("@{$result}\n"); # returns 3 5

2.3 Hash references

An hash reference is a reference to a hash:
%authors_books = (
'Scott Fitzgerald' => 'The Great Gatsby',
'John Steinbeck' => 'The Grapes of Wrath',
'Ernest Hemingway' => 'The Old Man and the Sea' );

$ref_authors_books = \%authors_books; # creates the reference, with a backslash before the hash sigil %
print($$ref_authors_books{"Ernest Hemingway"} . "\n"); # returns 'The Old Man and the Sea'
print($ref_authors_books->{"Ernest Hemingway"} . "\n"); # alternative, returns 'The Old Man and the Sea' also

3.4 References to subroutines

sub add {
($x, $y) = @_; # argument assigned to a list
return ($x + $y); # the subroutine returns the sum of $x and $y, which is equal to $_[0] + $_[1]
}

$sum1 = add(2,3);
print($sum1 . "\n"); # output: 5
$sub_ref = \&add; # creates the reference, with a backslash before the subroutine sigil &
$sum2 = &$sub_ref(2,3); # dereferencing with &
print($sum2 . "\n"); # output: 5
2.4.1 Passing array and subroutine references as arguments
Quite intriguing is the following code with two subroutines and passing an array and a subroutine as reference:
sub square {
return ($_[0] * $_[0]);
}

sub compute {
($array, $function) = @_;
foreach $element (@$array) {
push(@res, &$function($element));
}
return (@res);
}

@numbers = (2,3,5);
@result = compute(\@numbers, \&square);
print("@result\n"); # output: 4 9 25
It could be shorter:
sub square {
return ($_[0] * $_[0]);
}

sub compute {
($array, $function) = @_;
$_ = &$function($_) foreach (@$array);
}

@numbers = (2,3,5);
compute(\@numbers, \&square);
print("@numbers\n"); # output: 4 9 25
The trick is here that the 'foreach' loop changes the actual array element. So, you could skip extra variables and check the content of '@numbers'.

2.5 Anonymous arrays

Construct an anonymous array reference with square brackets: []:
$anon_array_ref = ['Sebastian', 'Daniel', 'Florence']; # $anon_ref is anonymous, because it points to an array that has no name
print("@$anon_array_ref\n"); # output: Sebastian Daniel Florence.
print("$anon_array_ref->[0]\n"); # output: Sebastian
print("$$anon_array_ref[0]\n"); # output: Sebastian
print("${$anon_array_ref}[0]\n"); # output: Sebastian

2.6 Anonymous hashes

Construct an anonymous hash reference with curly braces {}:
$anonymous_authors_books = { # $anonymous_authors_books is anonymous, because it points to a hash that has no name
'Scott Fitzgerald' => 'The Great Gatsby',
'John Steinbeck' => 'The Grapes of Wrath',
'Ernest Hemingway' => 'The Old Man and the Sea' };

print($$anonymous_authors_books{"Ernest Hemingway"} . "\n"); # returns 'The Old Man and the Sea'
print($anonymous_authors_books->{"Ernest Hemingway"} . "\n"); # alternative, but returns 'The Old Man and the Sea' also

2.7 Anonymous functions

$add_two = sub {
return shift(@_) + 2;
};

print $add_two->(3) . "\n"; # output: 5

2.8 Return an array or hash reference

Let's have a look to this code; The my keyword declares the variable @array. Its scoped within the subroutine. When the subroutine ends, @array goes out of scope and does not exist anymore.
sub square_ref {
my @array = (1 .. 5); # @array scoped within the subroutine via the 'my' keyword (1)
$_ = ($_ * $_) foreach (@array); # each value of @array is squared
return \@array # return the reference of @array
}

$res = square_ref();
print("@array\n"); # no output: @array is out of scope
print("@{$res}\n"); # output: 1 4 9 16 25
Two shorter alternatives, omitting an extra variable:
print("@{square_ref()}\n");
print("@{&square_ref}\n");
Returning a reference is efficient: Perl doesn't have to make copies of all the array elements when returning the array as subroutine value. The same is true when processing hashes.

Exit: arrow dereferencing

References to arrays, hashes, and subroutines can be dereferenced using the -> operator. For example, these three statement are equivalent and have as output 'Sebastian':
@kids = qw (Sebastian Daniel Florence);
$aref = \@kids;
print($$aref[0]);
print(${$aref}[0]);
print($aref->[0]);
The first statement dereferences first and then finds the first element of that array. This procedure is more clear in the second statement. The third statement uses the arrow notation and does the same thing.

The arrow dereferencing notation can only be used in expressions that return a single scalar value.


Footnotes
(1) Perl variables are by default global variables, which means that they can be accessed from anywhere in the program. Private variables (called lexical variables) can be created using 'my' operator: they are not accessible outside the block they are defined in.