I spend a few minutes here and there reading the ‘Alpaca’ book (Intermediate Perl) and feel its time to get a grip of references. It seems that a reference is only like a pointer in C so given that Perl is supposed to be ‘easier’ than C there should be no issue! I’m going to set up my own tests which I think are clearer than the book to aid my understanding.
First things first, my test program has an array of names which is passed to a function to ‘do something’ and the will return an array to the main program. I’ll then modify this program to use ‘references’.
#! /usr/bin/perl -w use strict; sub upper { my @a = @_; @a = sort(map { ucfirst($_) } @a); return @a; } my @array = qw/dan cath nads japes max aitch babs jimbo janet/; @array = &upper(@array); print "@array\n";
The names have been changed a bit to protect the innocent! the result is:
Aitch Babs Cath Dan Janet Japes Jimbo Max Nads
But what happened? Well the array dan cath nads japes max aitch babs jimbo janet
was copied to the function (ie it the existed twice in memory, the function executed (using the copy) and the result was copied into the original array. This is know as pass by value, and the important bit, aside from the fact that the extra memory is needed is that the function cannot alter the original array.
Our next step is to use a reference or pointer to pass by reference. The perl code to pass by reference is the backslash ‘\’ and the reference will be a simple scalar in our case, ie \@array
. Once we have passed the reference to the function, to get access to the array we need to use a another special notation which involved putting the scalar reference to the array in curly brackets, eg @{$reference_name}
. Individual array members can be addressed like this ${reference_name}[index]
. So lets give it a go…
#! /usr/bin/perl -w use strict; sub upper { my $array_ref = shift; @{$array_ref} = sort(map { ucfirst($_) } @{$array_ref}); } my @array = qw/dan cath nads japes max aitch babs jimbo janet/; &upper(\@array); print "@array\n";
I changed a few bits which I’ll explain. Firstly the function had the ‘return’ removed and the ‘shift’ is now used as we are only receiving a single scalar as the function argument. The array references have become @{$array_ref}
(formerly @a
). In the main program I just called the function adn passed by reference as you would expect using the \ symbol. Notice i don’t need the @array =
now as the function acted on the @array
directly. The results are as expected, exactly the same as before but with the smug, warm feeling of ‘passing by reference‘.
Lastly for this post, as with all things Perl, not only is there “more than one way to do it” which sometimes leads to confusion, there are also many ways to write the same thing and references are no exception, so @{$array_reference}
can be written as @$array_reference
when $array_reference
is a simple scalar.