返回哈希的子例程 - 将其分解为单独的变量
Posted
技术标签:
【中文标题】返回哈希的子例程 - 将其分解为单独的变量【英文标题】:Subroutine that returns hash - breaks it into separate variables 【发布时间】:2013-05-23 15:45:42 【问题描述】:我有一个返回哈希的子程序。子程序的最后几行:
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';
一旦哈希被破坏,我就不能再使用它了。 为什么会这样?以及如何在子程序返回时保持正确的结构?
谢谢, 标记。
【问题讨论】:
答案在你机械地插入到 Dumper() 调用中的 `\` 中:-) 【参考方案1】:为什么不返回对哈希的引用呢?
return \%fileDetails;
只要是词法变量,就不会因为子程序的其他用途而使事情复杂化。即:
sub fileDetails
my %fileDetails;
... # assign stuff
return \%fileDetails;
当执行离开子程序时,变量超出范围,但内存中包含的数据仍然存在。
Dumper 输出看起来像这样的原因是您为其提供了一个引用列表。子程序不能返回数组或散列,它们只能返回标量列表。你正在做的是这样的:
print Dumper \(qw(something 0 somethingelse 7.123 else burst));
【讨论】:
【参考方案2】:在列表上下文中,Perl 不区分散列和键/值对列表。也就是说,如果一个子程序return
s 是一个哈希,它真正返回的是一个(key1, value1, key2, value2...)
的列表。幸运的是,这是双向的。如果你把这样一个列表分配给一个哈希,你会得到一个原件的忠实副本:
my %fileDetailsCopy = subroutineName();
但如果它不会破坏其他代码,那么让 sub 返回对哈希的引用可能更有意义,正如 TLP 所说。
【讨论】:
【参考方案3】:你不能直接返回一个散列,但是 perl 可以根据需要在散列和列表之间自动转换。因此 perl 将其转换为列表,并且您将其捕获为列表。即
Dumper( filedetail() ) # list
my %fd = filedetail(); Dumper( \%fd ); #hash
【讨论】:
【参考方案4】:Perl 函数不能返回哈希值,只能返回列表。 return %foo
语句会将 %foo
展平为一个列表并返回展平后的列表。要将返回值解释为哈希,可以将其分配给命名的哈希
%new_hash = fileDetailsSub(...);
print Dumper(\%new_hash);
或cast it(不确定这是否是最好的词)与%...
操作序列:
print Dumper( \% fileDetailsSub(...) );
正如 TLP 指出的那样,另一种方法是从您的函数返回哈希引用。
【讨论】:
【参考方案5】:在 Perl 中没有返回哈希这样的东西。
子例程将 lists 作为参数,并且可以返回 lists 作为结果。请注意,列表与数组完全不同。
当你写作时
return %fileDetails;
这相当于:
return ( 'something', 0, 'somethingelse', 7.68016712043654, 'else', 'burst' );
当您调用子例程并取回该列表时,您可以做的一件事是将其分配给一个新的哈希:
my %result = fileDetailsSub();
之所以可行,是因为可以使用 list 键值对对哈希进行初始化。 (记住(foo => 42, bar => 43 )
和('foo', 42, 'bar', 43)
是一回事。
现在,当您在哈希上使用反斜杠引用运算符时,如\%fileDetails
,您会得到一个哈希引用,它是指向哈希的标量。
同样,如果你写\@array
,你会得到一个数组引用。
但是当您在 list 上使用引用运算符时,您不会得到对列表的引用(因为列表不是变量(它们是短暂的),它们不能被引用。 ) 相反,引用运算符分布在列表项上,所以
\( 'foo', 'bar', 'baz' );
创建一个新列表:
( \'foo', \'bar', \'baz' );
(在这种情况下,我们得到一个充满标量引用的列表。)这就是当您尝试 Dumper
子例程的结果时所看到的:一个引用运算符分布在从您返回的项目列表中子。
因此,一种解决方案是在使用 Dumper 之前将结果列表分配给实际的哈希变量。另一个是从子返回一个哈希引用(无论如何你正在倾倒):
return \%fileDetails;
...
my $details_ref = fileDetailsSub();
print Dumper( $details_ref );
# access it like this:
my $elem = $details_ref->something;
my %copy = % $details_ref ;
更多乐趣,请参见:
perldoc perlreftut - Perl 参考教程,以及 perldoc perlref - Perl 参考参考。【讨论】:
以上是关于返回哈希的子例程 - 将其分解为单独的变量的主要内容,如果未能解决你的问题,请参考以下文章