     Next: References to subroutines Up: Subroutines, functions, and modules Previous: Returning variables   Contents   Index

## Passing in and returning arrays and hashes

Passing in and returning arrays and hashes from subroutines involves some subtelties. Consider
```  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 is
```
which 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 10
```
Similar 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 5
```
What 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 100
```
The 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 \$sin = 12345;

sub print_info {
my (\$na, \$ag, \$ad, \$si) = @_;
print << "END";
The information we have is
Name: \$na
Age: \$ag
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 \$sin = 12345;
print_info(name => \$name,
age => \$age,
sin => \$sin);

sub print_info {
my (%info) = @_;
print << "END";
The information we have is
Name: \$info{name}
Age: \$info{age}     