Strictly speaking, you can't return an array or a hash from a Perl subroutine. Perl subroutines return lists. Lists are similar to arrays in that they're sequences of values, but they aren't arrays. Arrays are variables. Lists are nameless, immutable, and transient data structures used to pass and return values, initialize arrays and hashes, etc. It's a somewhat subtle point, but an important one.
When you write return @data
you aren't returning the @data
array; you're returning a list of the values it contains. Similarly, return %data
returns a list of the key/value pairs contained in the hash. Those values can be used to initialize another array or hash, which is what's happening in your examples. The initialized array/hash contains a (shallow) copy of the one used by the subroutine.
To "return" an array or hash, you must return a reference to it. e.g. return \@data
or return \%data
. Doing that returns a reference to the variable itself. Modifying it will affect the original array as well because it's the same storage.
Whether a sub should return an array/hash as a list (copy) or a reference is a programming decision. For subs that always return N values with positional meaning (e.g. the localtime
built-in) returning a list makes sense. For subs that return arbitrarily large lists it's usually better to return a reference instead as it's more efficient.
It's even possible for a sub to decide what to return based on how it's called by using wantarray
. This let's the caller decide what they want.
sub get_data {
my @data;
...
return wantarray ? @data : \@data;
}
my $aref = get_data(); # returns a reference
my @array = get_data(); # returns a list