From Robin's Wiki

PerlTips: ReferencesPassedToSubroutines

Sometimes it is handy to pass a reference to a data structure into a sub, which can then modify them. It isn't always the best programming practice really, but does have its place.

The reason that you may need to do this, is that in Perl, arguments are always passed around as lists, and lists can't be nested like in LISP. So (1, 2, ('a', 'b', 'c'), 3) is exactly the same as (1, 2, 'a', 'b', 'c', 3). This means that given the following code:

my @array1 = (1, 2, 3);
@array2 = ('a', 'b', 'c');
mySub(@array1, @array2);

The final call is equivalent to:

mySub(1, 2, 3, 'a', 'b', 'c');

which you probably don't want. To allow both lists to be passed in as seperate items, you need to pass them as references.

The passing of the reference in to the sub is quite easy:

mySub(\@array1, \@array2);

However, accessing this from within the sub is slightly more tricky. You need to put the reference into a scalar and dereference it when you use it:

sub mySub {
        my ($a1, $a2) = @_;
        # treating it as an array:
        push @$a1, 42;
        push @$a2, 24;
        # treating it as a scalar:
        print "First element: $$a1[0]\n";
}

A nicer way of doing this is:

sub mySub {
        my @a1 = @{ shift() };
        my @a2 = @{ shift() };
        push @a1, 42;
        print "First element: $a1[0]\n";.
}

You can avoid the need to call the sub with backslashes if you use a prototype:

sub mySub(\@\@) {
        my @a1 = @{ shift() };
        my @a2 = @{ shift() };
        push @a1, 42;
        # and so on, just like before
}

The difference with this is that the function may now be called like:

mySub(@array1, @array2);

which is much more natural. Note that you will likely need to place a prototype declaration near the top of your program. The declaration is simply:

sub mySub(\@\@);

Generalising this into hashes should be quite easy.

Retrieved from http://www.kallisti.net.nz/PerlTips/ReferencesPassedToSubroutines
Page last modified on December 02, 2009, at 07:44 AM