my @x = (1 .. 5); my @y = (6 .. 10); print_them(@x, @y); sub print_them { my (@a, @b) = @_; print qq{Array \@a is @a\n}; print qq{Array \@b is @b\n}; }This will print out
Array @a is 1 2 3 4 5 6 7 8 9 10 Array @b iswhich is probably not what you expect or want. The problem here is that the array @_ containing a list of arguments passed into the routine flattens out the list, so that in this example the ``boundary'' between the two arrays @x and @y disappears. In cases like this you can use array references:
my @x = (1 .. 5); my @y = (6 .. 10); print_them(\@x, \@y); sub print_them { my ($aref, $bref) = @_; print qq{Array \@a is }; for (@$aref) { print "$_ "; } print qq{\nArray \@b is }; for (@$bref) { print "$_ "; } print "\n"; }which will output
Array @a is 1 2 3 4 5 Array @b is 6 7 8 9 10Similar considerations hold for returning multiple arrays. Just as for scalar variables, though, you should be aware of the effects of passing in arrays by reference. Consider
my @x = (1 .. 5); print qq{Before the sub, \@x is @x\n}; test_it(@x); print qq{After the sub, \@x is @x\n}; sub test_it { my @a = @_; print qq{Within the sub, \@a is initially @a\n}; for my $element (@a) { $element *= 20; } print qq{Within the sub, \@a is finally @a\n}; }which reports
Before the sub, @x is 1 2 3 4 5 Within the sub, @a is initially 1 2 3 4 5 Within the sub, @a is finally 20 40 60 80 100 After the sub, @x is 1 2 3 4 5What happens here is that the array @x gets passed into the subroutine, and a copy of it is made, with the copy being called @a. We then mess with the values of the copy, but upon returning from the subroutine, the original values of @x are unchanged. Consider however passing in the array by reference:
my @x = (1 .. 5); print qq{Before the sub, \@x is @x\n}; test_it(\@x); print qq{After the sub, \@x is @x\n}; sub test_it { my $aref = shift; print qq{Within the sub, \@a is initially @$aref\n}; for my $element (@$aref) { $element *= 20; } print qq{Within the sub, \@a is finally @$aref\n}; }In this case we find
Before the sub, @x is 1 2 3 4 5 Within the sub, @a is initially 1 2 3 4 5 Within the sub, @a is finally 20 40 60 80 100 After the sub, @x is 20 40 60 80 100The modifications we did to the array within the subroutine are now reflected in the original values! This is a fundamental property of passing in something by reference, and is analagous to what happens in C when pointers are used. Sometimes this property is very useful and powerful, and sometimes it is annoying - either way, it is something one has to be aware of when working with references.
Passing in and returning hashes from subroutines follows a very similar discussion, as does the need at times for using hash references. Hashes are often used to pass an argument list into a subroutine when many arguments are present; consider
my $name = 'Lianne'; my $age = 22; my $address = '123 Oak'; my $sin = 12345; print_info($name, $age, $address, $sin); sub print_info { my ($na, $ag, $ad, $si) = @_; print << "END"; The information we have is Name: $na Age: $ag Address: $ad SIN: $si END }Here the order of the variables passed into the subroutine are crucial at getting the correct behaviour. However, if we write this using hashes as
my $name = 'Lianne'; my $age = 22; my $address = '123 Oak'; my $sin = 12345; print_info(name => $name, address => $address, age => $age, sin => $sin); sub print_info { my (%info) = @_; print << "END"; The information we have is Name: $info{name} Age: $info{age} Address: $info{address} SIN: $info{sin} END }then we have an effective ``named'' argument list and can pass in the arguments in any order we choose.