Tweet

Dereferencing in perl

References are commonly used when you are returning a large object or data structure (for example an array or hash) from a subroutine. Instead of returning a copy of the entire data structure, you return a pointer to the structure. This makes your programs more efficient. You can also use references to subroutines and scalars.

When you want to actually use the values in these variables, you need to dereference the pointer. This page shows you how this works in Perl.

Creating references

You can create a reference to a variable or subroutine by using the backslash (\) operator. For example, the following subroutine returns a reference to the array @fruit.

    sub fruit_i_like() {
        my @fruit = ('apple', 'banana', 'orange');
        return \@fruit;
    }

The code to call this subroutine would look like:

    my $fruit = fruit_i_like();

The fruit_i_like() subroutine returns a scalar variable so that $fruit will hold a reference to the @fruit array.

This works the same with scalars, hashes and subroutines:

    my $scalar_ref = \$a_scalar;
    my $hash_ref = \%a_hash;
    my $subroutine_ref = \&a_subroutine;

You can create a reference to an anonymous array or hash by using square brackets for an array and braces for a hash:

    my $array_ref = ['apple', 'banana', 'orange'];
    my $hash_ref = {name => 'Becky', age => 23};

Similarly, you can create a reference to an anonymous subroutine:

    my $sub_ref = sub { print "In a subroutine\n" };

Filehandles can also be referenced. You do this by using a reference to a typeglob (see perldoc perldata):

    do_something(\*FILEHANDLE);
    sub do_something($) {
        my ($filehandle) = @_;
        print $filehandle "Something\n";
    }

Dereferencing - part 1

A simple way of dereferencing is to put the appropriate identifier (sigil) in front of the reference. For example, the following code creates a reference to a scalar, and prints both the reference and the dereferenced value so that you can see that the reference is actually a reference:

    #!/usr/bin/perl
    use strict;
    use warnings;

    my $scalar = "This is a scalar";
    my $scalar_ref = \$scalar;

    print "Reference: " . $scalar_ref . "\n";
    print "Dereferenced: " . $$scalar_ref . "\n";

This produces something like:

    Reference: SCALAR(0x80fea8c)
    Dereferenced: This is a scalar

In the same way, to dereference an array reference, hash reference or a subroutine reference, you put the appropriate identifier (sigil) before the reference. Here is a array reference example:

    #!/usr/bin/perl
    use strict;
    use warnings;

    my $array_ref = ['apple', 'banana', 'orange'];
    my @array = @$array_ref;

    print "Reference: $array_ref\n";
    print "Dereferenced: @array\n";

The output is:

    Reference: ARRAY(0x80f6c6c)
    Dereferenced: apple banana orange

And a hash reference example:

    #!/usr/bin/perl
    use strict;
    use warnings;

    my $hash_ref = {name => 'Becky', age => 23};
    my %hash = %$hash_ref;

    print "Reference: $hash_ref\n";
    print "Dereferenced:\n";
    foreach my $k (keys %hash) {
        print "$k: $hash{$k}\n";
    }

The output of this program is:

    Reference: HASH(0x80f6c6c)
    Dereferenced:
    name: Becky
    age: 23

And a subroutine reference example:

    #!/usr/bin/perl
    use strict;
    use warnings;

    my $sub_ref = sub { print "In a subroutine\n" };

    &$sub_ref();

This calls the subroutine and produces:

    In a subroutine

Dereferencing - part 2

Another similar way of dereferencing is to use a block (in curly braces). For example, the example above that uses a scalar reference would be re-written as:

    #!/usr/bin/perl
    use strict;
    use warnings;

    my $scalar = "This is a scalar";
    my $scalar_ref = \$scalar;

    print "Reference: " . $scalar_ref . "\n";
    print "Dereferenced: " . ${$scalar_ref} . "\n";

While this looks like only two extra characters, the block is helpful when your reference is stored in a hash or other data structure:

    #!/usr/bin/perl
    use strict;
    use warnings;

    my %hash = (frogs => sub {print "Frogs\n"});

    &{ $hash{frogs} }();

Dereferencing - part 3

The arrow operator also allows you to dereference references to arrays or hashes. The arrow operator makes more complex structures easier to read. The first example shows accessing an element of an array reference:

    #!/usr/bin/perl
    use strict;
    use warnings;

    my $array_ref = ['apple', 'banana', 'orange'];
    print "My first fruit is: " . $array_ref->[0] . "\n";

This would produce the following output:

    My first fruit is: apple

The next example shows accessing elements of an hash reference:

    #!/usr/bin/perl
    use strict;
    use warnings;

    my $hash_ref = {name => 'Becky', age => 23};
    foreach my $k (keys %$hash_ref) {
        print "$k: " . $hash_ref->{$k} . "\n";
    }

This produces the following output:

    age: 23
    name: Becky

Subroutine references work the same way, using parenthesis:

    #!/usr/bin/perl
    use strict;
    use warnings;

    my %hash = (frogs => sub {print "Frogs\n"});
    $hash{frogs}->();

The ref operator

The handy perl 'ref' operator tells you what type of reference your variable is. This means that you can write a subroutine that takes a different action based on the type of reference it received. In the following example, the subroutine write_to_file writes the passed in $message to the given filehandle, however it writes the message differently depending on whether the variable is a scalar value, an array reference or a hash reference.

    #!/usr/bin/perl
    use strict;
    use warnings;

    sub write_to_file($$);

    open (FILEHANDLE, ">test.txt") or die $!;

    print write_to_file(\*FILEHANDLE, "A log");
    print write_to_file(\*FILEHANDLE, ['apple', 'banana', 'orange']);
    print write_to_file(\*FILEHANDLE, {name => 'Becky', age => 23});

    close FILEHANDLE;

    sub write_to_file($$) {
        my ($filehandle, $message) = @_;
        if (ref($message) eq 'ARRAY') {
            print $filehandle "@$message\n";
        } elsif (ref($message) eq 'HASH') {
            foreach my $k (keys %$message) {
                print $filehandle "$k: " . $message->{$k} . "\n";
            }
        } else {
            print $filehandle "$message\n";
        }
    }

The above example would produce a file with the following contents:

    A log
    apple banana orange
    age: 23
    name: Becky

See also

    perldoc perldsc (for detailed examples of perl data structures)
    perldoc perldata
Revision: 1.3 [Top]