将多个哈希作为参数传递给 Perl 子程序 (Perl 5.16 / Perl 5.30)
我们试图将多个散列与一堆标量一起作为参数传递给子程序。问题在于这个子程序的多次调用,(如果我们在函数内部检索到两个哈希值后打印它们),只有其中一个(第一个)获得了正确的值。第二个是空的。我们尝试了很多东西-
1 ) 两个单独的散列,具有来自 Stackoverflow/PerlMonks 等的不同语法,并作为参考传递。
&mySub(\%hash0, \%hash1, $var0, $var1, $var2);
sub mySub{
my (%hash0, %hash1, $var0, $var1, $var2) = (@_);
}
或者
&mySub(\%hash0, \%hash1, $var0, $var1, $var2);
sub mySub{
my %hash0 = %{$_[0]};
my %hash1 = %{$_[1]};
my $var0 = $[2]; my $var1 = $[3]; my $var3 = $[4];
}
2)创建两个散列的数组并通过
my @joined_arr = (\%hash0, \%hash1);
&mySub (\@joined_arr, $var0, $var1, $var2);
sub mySub{
my (@joined_arr, $var0, $var1, $var2) = (@_);
my %hash0 = %{joined_arr[0]};
my %hash1 = %{joined_arr[1]};
# rest of the variables.
}
4)创建散列的散列并通过
my %joined_hash;
%joined_hash{"first_one"} = %hash0;
%joined_hash{"second_one"} = %hash1;
&mySub (\%joined_hash, $var0, $var1, $var2);
sub mySub{
my %joined_hash, %hash0, %hash1;
%joined_hash = %{$_[0]};
%hash0 = %joined_hash{"first_one"};
%hash1 = %joined_arr{"second_one"};
# rest of the variables.
}
- 在 Perl 5.16(CentOS 7 的默认发行版)和 Perl 5.30 中尝试它们。
到目前为止,这还没有成功。如果有人有想法并喜欢分享,那将是非常有帮助的。
编辑
按照@zdim 和@Polar Bear 的建议,我尝试了这些东西->
将@_ 卸载到函数内部的标量的语法 ->
一种)
my ($ref_to_hash0, $ref_to_hash1, $var0, $var1, $var2) = @_;
b)
$ref_to_hash0 = shift;
$ref_to_hash1 = shift;
$var0 = shift;
$var1 = shift;
$var2 = shift;
我也尝试过这 3 种散列引用的散列分配样式。
一种)
my %local_hash_shallow_copy = %$ref_to_hash0;
b)
my $local_hashref_deep_copy = dclone $ref_to_hash0;
C)
my %local_hash_shallow_copy = %{$ref_to_hash0};
似乎在这个 sub 调用的 9 次迭代中,我在 sub 中获得了正确的哈希值 2 次。在其他时候,我只是得到一个指针转储 -
$VAR1 = {
'HASH(0x1e32cc8)' => undef
};
我正在使用 Dumper 在外部转储散列 - 就在 sub 调用之前,就在内部 - 就在我将值从 ref 转移到实际散列之后。这应该避免任何愚蠢的错误。
要么我在这里犯了一个非常基本的错误,要么遇到了一个不可思议的问题。正在调试。
供参考。
回答
Perl 中的函数调用将标量列表作为参数传递,这就是您正确执行的操作。该函数接收 中的标量列表@_,它们是这些参数的别名。
所以随着电话†
mySub(\%hash0, \%hash1, $var0, $var1, $var2);
该函数有@_五个标量,前两个是感兴趣的散列引用。
但是现在您将它们分配给哈希!
sub mySub{
my (%hash0, %hash1, $var0, $var1, $var2) = (@_); # WRONG
}
使%hash0填充了一切的@_,如
%hash = (\%hash0 => \%hash1, $var0 => $var1, $var2 => undef);
因为连续的标量被分配为键值对。列表中以 开头的其余变量%hash1也作为该子例程中的词法符号引入,并且是undef。
如果参数数量确实是奇数,您应该收到警告。(use warnings;你的程序顶部有一行,对吗?)
需要将元素分配@_给合适的标量,例如
sub mySub{
my ($ref_to_hash0, $ref_to_hash1, $var0, $var1, $var2) = @_;
}
现在你有两个选择如何使用它
-
foreach my $key (keys %$ref_to_hash0) { $ref_to_hash0->{$key} ... }简而言之,这是
-
$ref_to_hash0->{some_key} = 'value'; # changes data IN THE CALLER这可能很方便,也可能很危险(因为它可能被错误地完成)
-
use Storable qw(dclone); # may be needed sub mySub{ my ($ref_to_hash0, $refhash1, $var0, $var1, $var2) = @_; # If the caller's %hash0 has no references for values just dereference # Tricky though -- what when the calling hash changes in the future? my %local_hash_shallow_copy = %$ref_to_hash0; # If the caller's %hash0 is a complex data structure, need a deep copy my $local_hashref_deep_copy = dclone $ref_to_hash0; # Changes to local hash/hashref do not affect data in the caller }
†通常不需要&在问题中的名称前面使用,此处省略,除非您打算在调用中隐藏其原型。