You can easily find confusing definitions of a Perl reference. Let's avoid this now!
Scalar references are not very common.$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
@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
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_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
A bit more concisesub 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
and more efficient (see Chapter 3.8 below)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
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
%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
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
It could be shorter: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
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'.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
$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
$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
$add_two = sub {
return shift(@_) + 2;
};
print $add_two->(3) . "\n";# output: 5
Two shorter alternatives, omitting an extra variable: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
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.print("@{square_ref()}\n");
print("@{&square_ref}\n");
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.@kids = qw (Sebastian Daniel Florence);
$aref = \@kids;
print($$aref[0]);
print(${$aref}[0]);
print($aref->[0]);