Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 返回散列的子例程-将其分解为单独的变量_Perl_Function_Return_Hashtable - Fatal编程技术网

Perl 返回散列的子例程-将其分解为单独的变量

Perl 返回散列的子例程-将其分解为单独的变量,perl,function,return,hashtable,Perl,Function,Return,Hashtable,我有一个返回散列的子程序。子程序的最后几行: print Dumper(\%fileDetails); return %fileDetails; 在这种情况下,自卸车打印: $VAR1 = { 'somthing' => 0, 'somthingelse' => 7.68016712043654, 'else' => 'burst' } $VAR1 = \'somthing'; $VAR2 = \0; $VAR3

我有一个返回散列的子程序。子程序的最后几行:

print Dumper(\%fileDetails);
return %fileDetails;
在这种情况下,自卸车打印:

$VAR1 = {
          'somthing' => 0,
          'somthingelse' => 7.68016712043654,
          'else' => 'burst'
}
$VAR1 = \'somthing';
$VAR2 = \0;
$VAR3 = \'somthingelse';
$VAR4 = \7.68016712043654;
$VAR5 = \'else';
$VAR6 = \'burst';
但是当我试图用这行调用子程序来转储它时:

print Dumper(\fileDetailsSub($files[$i]));
翻车机打印:

$VAR1 = {
          'somthing' => 0,
          'somthingelse' => 7.68016712043654,
          'else' => 'burst'
}
$VAR1 = \'somthing';
$VAR2 = \0;
$VAR3 = \'somthingelse';
$VAR4 = \7.68016712043654;
$VAR5 = \'else';
$VAR6 = \'burst';
一旦散列被破坏,我就不能再使用它了。 为什么会这样?如何在子例程返回时保持正确的结构

谢谢,
标记。

为什么不返回对散列的引用呢

return \%fileDetails;
只要它是一个词法变量,它就不会使子例程的其他用途复杂化。即:

sub fileDetails {
    my %fileDetails;
    ... # assign stuff
    return \%fileDetails;
}
当执行离开子例程时,变量将超出范围,但内存中包含的数据将保留

转储程序输出看起来像这样的原因是您正在向它提供一个引用列表。子例程不能返回数组或散列,它们只能返回标量列表。你正在做的事情是这样的:

print Dumper \(qw(something 0 somethingelse 7.123 else burst));

在列表上下文中,Perl不区分散列和键/值对列表。也就是说,如果子例程
返回一个散列,那么它真正返回的是
列表(key1,value1,key2,value2…
)。幸运的是,这是双向的;如果您获取这样一个列表并将其分配给散列,您将获得原始列表的忠实副本:

my %fileDetailsCopy = subroutineName();

但是如果它不会破坏其他代码,那么让sub返回对散列的引用可能更有意义,正如TLP所说。

您不能直接返回散列,但是perl可以根据需要自动在散列和列表之间转换。所以perl将其转换为一个列表,并将其捕获为一个列表。i、 e

Dumper( filedetail() ) # list
my %fd = filedetail(); Dumper( \%fd ); #hash

Perl函数不能返回哈希,只能返回列表。
return%foo
语句将把
%foo
展平到一个列表中,并返回展平的列表。要获取要解释为散列的返回值,可以将其分配给命名散列

%new_hash = fileDetailsSub(...);
print Dumper(\%new_hash);
或者(不确定这是否是最好的词)具有
%{{…}
操作序列:

print Dumper( \%{ {fileDetailsSub(...)} } );

正如TLP所指出的,另一种方法是从函数返回散列引用。

在Perl中没有返回散列这样的事情

子例程将列表作为其参数,并且可以返回列表作为其结果。请注意,列表与阵列是完全不同的生物

当你写作时

return %fileDetails;
这相当于:

return ( 'something', 0, 'somethingelse', 7.68016712043654, 'else', 'burst' );
当调用子例程并取回该列表时,可以做的一件事是将其分配给新的哈希:

my %result = fileDetailsSub();
这是因为可以使用键值对列表初始化哈希。(请记住
(foo=>42,bar=>43)
('foo',42,'bar',43)
是一样的

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

类似地,如果您编写
\@array
,您将获得一个数组引用

但是,当您在列表上使用reference操作符时,您不会得到对列表的引用(因为列表不是变量(它们是短暂的),所以不能被引用)。相反,reference操作符分布在列表项上,因此

\( 'foo', 'bar', 'baz' );
创建一个新列表:

( \'foo', \'bar', \'baz' );
(在本例中,我们得到一个满是标量引用的列表。)这就是当您尝试
转储子例程的结果时所看到的:一个引用操作符分布在从子例程返回的项目列表上

因此,一种解决方案是在使用转储程序之前将结果列表分配给一个实际的哈希变量。另一种解决方案是从子列表返回一个哈希引用(您正在转储的内容):

return \%fileDetails;

...

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

# access it like this:
my $elem = $details_ref->{something};
my %copy = %{ $details_ref };
有关更多乐趣,请参见:

  • -Perl参考教程,以及
  • -Perl参考

答案就在``中,您机械地将其插入到Dumper()调用中:-)