When to return an array or a hash and when only a reference?

I am confused about the following. Sometimes I see examples like this:

my %hash = get_data();

sub get_data {
    my %data = ();
    # do processing
    return %data;
}

      

And similarly with arrays.

my @arrays = get_data();

sub get_data {
    my @data = ();
    # do processing
    return @data;
}

      

I originally thought that you cannot return arrays or hashes from functions, just references to them.
So I don’t understand what is the difference and when do we prefer each other?
Is it due to garbage collection or too large a copy of the data that we choose?

+3


source to share


2 answers


Strictly speaking, you cannot return an array or hash from a Perl subroutine. Perl routines return. Lists are like arrays in that they are sequences of values, but they are not arrays. Arrays are variables. Lists are unnamed, immutable, and temporary data structures used to pass and return values, initialize arrays and hashes, and more. This is a somewhat subtle point , but important.

When you write return @data

, you are not returning an array @data

; you are returning a list of values ​​it contains. Likewise, it return %data

returns a list of the key / value pairs contained in the hash. These values ​​can be used to initialize another array or hash, which is what happens in your examples. The initialized array / hash contains a (shallow) copy of the one used by the routine.

To "return" an array or hash, you must return a reference to it. for example return \@data

or return \%data

. Doing this returns a reference to the variable itself. Changing this setting will also affect the original array because they are the same storage.



Whether Sub should return an array / hash as a list (copy) or a reference is a programming decision. For subs that always return N positional-valued values ​​(eg inline localtime

), returning a list. For subsets returning arbitrarily large lists, it is usually best to return a link because it is more efficient.

It's even possible that south can decide what to return based on how it's called using wantarray

. This allows the caller to 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

      

+9


source


In fact, you are creating a new array (or hash) filled with the same elements as the one generated in sub:

sub get_data{
    # initialize an array
    my @toReturn = qw/ a b c d e f g /;

    # get its location in memory
    my $toReturn_ref = \@toReturn;

    # print its location in memory
    print "toReturn: $toReturn_ref\n";

    # return the **elements** in the array (not the array itself)
    return @toReturn;
}

# initialize an array
my @arr = get_data();

# get its location in memory
my $arr_ref = \@arr;

# print its location in memory
print "\"Returned\": $arr_ref\n";

      

This will print something like:



toReturn:   ARRAY(0x1df85e8)
"Returned": ARRAY(0x1debc40)

      

They are different arrays but have the same content.

+3


source







All Articles