References #1

#0 | #1

references

references are a data structure added to Perl in version 5. They work with hashes, arrays and subroutines, allowing us to now build and access some very complicated data structures. They are similar to C pointers.

Hash and array values can only hold scalar data - either a string or a number.

A reference is a scalar value, but it refers to an entire hash or array (as well as other things). Consider them like names for arrays or hashes. This will make more sense when we talk about how to use references.

So we can now have hashes of references to arrays, hashes of references to hashes, arrays of references to arrays, etc.

These are typically shortened to 'hash of arrays', 'hash of hashes', 'array of arrays', etc.

How do we make a reference?

  1. put a \ (backslash) in front of a variable
  2. use { } or [ ] to make references to a hash or array

For example ... (method 1)

    $aref = \@array;         # $aref now holds a reference to @array
    $href = \%hash;          # $href now holds a reference to %hash

The second method to make a reference is useful when you don't want or need a name for the hash or array ...

    $aref = [ 1, "foo", undef, 13 ];  # $aref now holds a reference to an array
    $href = { APR => 4, AUG => 8 };   # $href now holds a reference to a hash

This method is a short cut to first making a hash / array, then making a reference to it. The named hash / array is not created.

Make a reference:

  1. put a \ (backslash) in front of a variable
  2. Example:
  3. use { } or [ ] to make references to a hash or array
  4. Example:

In this case, $aref and $href makes an anonymous array / hash, and returns the reference to it.

Being a scalar variable, a reference can now be copied or stored like any other scalar!

    $xy = $aref;             # $xy now holds a reference to @array
    $p[3] = $href;           # $p[3] now holds a reference to %hash
    $z = $p[3];              # $z now holds a reference to %hash

How do we use a reference?


When you 'use' a reference, it is called dereferencing.

You, as the programmer, have the responsibility to explicitly dereference a hash, array, or subroutine if it holds a reference. Perl does not do this for you.

Now the fun begins. Recall how we said that references are like names for arrays or hashes? This means exactly that - where you would normally use @a, you would now use @{$aref}.

If $aref contains a reference to an array, then you can put {$aref} anywhere you would normally put the name of an array. For example, @{$aref} instead of @array.

@a		@{$aref}		An array
reverse @a	reverse @{$aref}	Reverse the array
$a[3]		${$aref}[3]		An element of the array
$a[3] = 17;	${$aref}[3] = 17	Assigning an element

Hash references are used the same way: where you would use %hash for a hash, you would use %{$href} to use the reference to it.

Note that in both cases, the name of the reference is wrapped in braces.

%h		%{$href}		A hash
keys %h		keys %{$href}		Get the keys from the hash
$h{'red'}	${$href}{'red'}		An element of the hash
$h{'red'} = 17	${$href}{'red'} = 17	Assigning an element

To demonstrate a hash of hashes (hash of references to a hash), I will use some familiar data: months of the year. To do this I'll use the 2nd method described above, using braces { } to create an anonymous hash.

my $monthsRef = {
        "03"    => {
            short   => "MR",
            long    => "March",
        },
        "01"    => {
            short   => "JA",
            long    => "January",
        },
        "04"    => {
            short   => "AP",
            long    =>"April",
        },
        "06"    => {
            short   => "JE",
            long    => "June",
        },
        "02"    => {
            short   => "FE",
            long    => "February",
        },
        "05"    => {
            short   => "MY",
            long    => "May",
        },
        "07"    => {
            short   => "JL",
            long    => "July",
        },
        "12"    => {
            short   => "DE",
            long    => "December",
        },
        "09"    => {
            short   => "SE",
            long    => "September",
        },
        "08"    => {
            short   => "AU",
            long    => "August",
        },
        "10"    => {
            short   => "OC",
            long    => "October",
        },
        "11"    => {
            short   => "NO",
            long    => "November",
        },
};

To clarify:

The structure of your hash depends on how you intend to use it. In this case I decided to use the numeric value of each month as the key, so it could be sorted in the right 'monthly' order. Using the month names as keys, would not allow us to 'sort' them properly.

We hope you note that the original order of the hash is NOT in any particular order. But we sort the hash on keys - that is why I chose to do it this way.

Here is how we print this structure:

foreach my $k (sort keys %{$monthsRef}) {
    print qq/${$monthsRef}{$k}{short} \t $k \t ${$monthsRef}{$k}{long}\n/;
}

Note I used a front-slash / to wrap my quoted string.

To avoid the use of ${$, we could have used the infix operator -> :

foreach my $k (sort keys $monthsRef) {
    print qq/$k \t $monthsRef->{$k}->{short} \t $monthsRef->{$k}->{long}\n/;}