我有一个返回哈希的子程序。子程序的最后几行:
print Dumper(\%fileDetails);
return %fileDetails;
在这种情况下,翻斗车打印:
$VAR1 = {
'somthing' => 0,
'somthingelse' => 7.68016712043654,
'else' => 'burst'
}
但是当我尝试转储它时用这一行调用子程序:
print Dumper(\fileDetailsSub($files[$i]));
翻斗车打印:
$VAR1 = \'somthing';
$VAR2 = \0;
$VAR3 = \'somthingelse';
$VAR4 = \7.68016712043654;
$VAR5 = \'else';
$VAR6 = \'burst';
一旦哈希被破坏,我就不能再使用它了。 为什么会这样?如何在子程序返回时保留适当的结构?
谢谢, 标记
答案 0 :(得分:9)
没有在Perl中返回哈希的事情。
子程序将列表作为参数,并且可以返回列表作为结果。请注意,列表是与数组完全不同的生物。
写作时
return %fileDetails;
这相当于:
return ( 'something', 0, 'somethingelse', 7.68016712043654, 'else', 'burst' );
当您调用子例程并返回该列表时,您可以做的一件事就是将其分配给新的哈希:
my %result = fileDetailsSub();
这是有效的,因为可以使用键值对的列表初始化哈希。 (请注意,(foo => 42, bar => 43 )
与('foo', 42, 'bar', 43)
相同。
现在,当你在哈希上使用反斜杠引用运算符时,就像在\%fileDetails
中一样,你得到一个哈希引用,它是一个标量,指向一个哈希值。
同样,如果你写\@array
,你会得到一个数组引用。
但是当您在列表上使用引用运算符时,您不会获得对列表的引用(因为列表不是变量(它们是短暂的),它们可以'引用。)相反,引用运算符分配列表项,所以
\( 'foo', 'bar', 'baz' );
创建一个新列表:
( \'foo', \'bar', \'baz' );
(在这种情况下,我们得到一个充满标量引用的列表。)当你尝试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 };
更多乐趣,请参阅:
答案 1 :(得分:8)
为什么不返回对哈希的引用呢?
return \%fileDetails;
只要它是一个词法变量,它就不会使子程序的其他用途复杂化。即:
sub fileDetails {
my %fileDetails;
... # assign stuff
return \%fileDetails;
}
当执行离开子程序时,变量超出范围,但内存中包含的数据仍然存在。
Dumper输出看起来像是你给它一个引用列表。子例程不能返回数组或哈希值,它们只能返回标量列表。你在做什么是这样的:
print Dumper \(qw(something 0 somethingelse 7.123 else burst));
答案 2 :(得分:3)
Perl函数不能返回哈希值,只能返回列表。 return %foo
语句会将%foo
压缩到列表中并返回展平列表。要将返回值解释为散列,可以将其分配给命名散列
%new_hash = fileDetailsSub(...);
print Dumper(\%new_hash);
使用%{{...}}
操作序列或cast it(不确定这是否是最好的词):
print Dumper( \%{ {fileDetailsSub(...)} } );
正如TLP所指出的,另一种方法是从函数返回哈希引用。
答案 3 :(得分:1)
您不能直接返回哈希,但perl可以根据需要自动在哈希和列表之间进行转换。因此perl将其转换为列表,并将其作为列表捕获。即。
Dumper( filedetail() ) # list
my %fd = filedetail(); Dumper( \%fd ); #hash
答案 4 :(得分:0)
在列表上下文中,Perl不区分散列和键/值对列表。也就是说,如果子例程return
是一个哈希,它真正返回的是一个(key1, value1, key2, value2...)
列表。幸运的是,这两种方式都有效;如果您使用这样的列表并将其分配给哈希,您将获得原始的忠实副本:
my %fileDetailsCopy = subroutineName();
但是如果它不会破坏其他代码,那么让子返回对哈希的引用可能更有意义,就像TLP所说的那样。