返回哈希的子例程 - 将其分解为单独的变量

Mar*_*ark 6 perl return hashtable function

我有一个返回哈希的子程序.子程序的最后一行:

print Dumper(\%fileDetails);
return %fileDetails;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,翻斗车打印:

$VAR1 = {
          'somthing' => 0,
          'somthingelse' => 7.68016712043654,
          'else' => 'burst'
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试转储它时用这一行调用子程序:

print Dumper(\fileDetailsSub($files[$i]));
Run Code Online (Sandbox Code Playgroud)

翻斗车打印:

$VAR1 = \'somthing';
$VAR2 = \0;
$VAR3 = \'somthingelse';
$VAR4 = \7.68016712043654;
$VAR5 = \'else';
$VAR6 = \'burst';
Run Code Online (Sandbox Code Playgroud)

一旦哈希被破坏,我就不能再使用它了.为什么会这样?如何在子程序返回时保留适当的结构?

谢谢,马克.

fri*_*edo 9

没有在Perl中返回哈希的事情.

子例程将列表作为参数,它们可以返回列表作为结果.请注意,列表是一个与数组完全不同的生物.

当你写作

return %fileDetails;
Run Code Online (Sandbox Code Playgroud)

这相当于:

return ( 'something', 0, 'somethingelse', 7.68016712043654, 'else', 'burst' );
Run Code Online (Sandbox Code Playgroud)

当您调用子例程并返回该列表时,您可以做的一件事是将其分配给新的哈希:

my %result = fileDetailsSub();
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为可以使用键值对列表初始化哈希.(请记住,这(foo => 42, bar => 43 )是一样的('foo', 42, 'bar', 43).

现在,当您在散列上使用反斜杠引用运算符时\%fileDetails,您将获得一个散列引用,该散列引用是指向散列的标量.

同样,如果你写\@array,你会得到一个数组引用.

但是当您在列表中使用引用运算符时,您不会获得对列表的引用(因为列表不是变量(它们是短暂的),它们不能被引用.)而是引用运算符分配列表项所以

\( 'foo', 'bar', 'baz' );
Run Code Online (Sandbox Code Playgroud)

列出一个新列表:

( \'foo', \'bar', \'baz' );
Run Code Online (Sandbox Code Playgroud)

(在这种情况下,我们得到一个充满标量引用的列表.)这是您在尝试Dumper子例程的结果时所看到的:一个引用运算符分布在从子表返回的项目列表中.

因此,一种解决方案是在使用Dumper之前将结果列表分配给实际的哈希变量.另一种方法是从sub返回一个哈希引用(无论如何你都是Dumpering):

return \%fileDetails;

...

my $details_ref = fileDetailsSub();
print Dumper( $details_ref );

# access it like this:
my $elem = $details_ref->{something};
my %copy = %{ $details_ref };
Run Code Online (Sandbox Code Playgroud)

有关更多乐趣,请参阅:


TLP*_*TLP 8

为什么不返回对哈希的引用呢?

return \%fileDetails;
Run Code Online (Sandbox Code Playgroud)

只要它是一个词法变量,它就不会使子程序的其他用途复杂化.即:

sub fileDetails {
    my %fileDetails;
    ... # assign stuff
    return \%fileDetails;
}
Run Code Online (Sandbox Code Playgroud)

当执行离开子例程时,变量超出范围,但内存中包含的数据仍然存在.

Dumper输出看起来像是你给它一个引用列表.子例程不能返回数组或哈希值,它们只能返回标量列表.你在做什么是这样的:

print Dumper \(qw(something 0 somethingelse 7.123 else burst));
Run Code Online (Sandbox Code Playgroud)