什么时候返回数组或哈希,什么时候只引用?

时间:2014-09-10 12:36:28

标签: arrays perl function hash reference

我对以下内容感到困惑 有时我会看到这样的例子:

my %hash = get_data();

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

与数组类似。

my @arrays = get_data();

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

我原本以为你不能从函数返回数组或哈希只引用它们 所以我不明白有什么区别,我们什么时候应该优先于另一方呢? 它与垃圾收集或我们选择的数据副本太多有关吗?

2 个答案:

答案 0 :(得分:11)

严格地说,您不能从Perl子例程返回数组或哈希。 Perl子例程返回列表。列表类似于数组,因为它们是值的序列,但它们不是数组。数组是变量。列表是无名,不可变和瞬态数据结构,用于传递和返回值,初始化数组和散列等。它是somewhat subtle point,但是很重要。

当你写return @data时,你没有返回@data数组;您将返回其包含的值列表。类似地,return %data返回散列中包含的键/值对的列表。这些值可用于初始化另一个数组或散列,这正是您的示例中发生的情况。初始化的数组/哈希包含子例程使用的副本的(浅)副本。

要“返回”数组或散列,必须返回对它的引用。例如return \@datareturn \%data。这样做会返回对变量本身的引用。修改它也会影响原始数组,因为它是相同的存储。

sub是否应该将数组/散列作为列表(副本)或引用返回是编程决策。对于总是返回具有位置意义的N值的subs(例如内置localtime),返回列表是有意义的。对于返回任意大型列表的subs,通常最好返回一个引用,因为它更有效。

甚至可以让sub根据使用wantarray调用的方式来决定返回什么。这让打电话者决定他们想要什么。

sub get_data {
    my @data;
    ...
    return wantarray ? @data : \@data;
}

my $aref  = get_data(); # returns a reference
my @array = get_data(); # returns a list

答案 1 :(得分:3)

您实际上是在创建一个新数组(或哈希),其中填充的元素与在子数据库中生成的元素相同:

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";

这将打印如下内容:

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

它们是不同的数组,但恰好具有相同的内容。