【发布时间】:2017-12-21 11:27:51
【问题描述】:
我已经创建了这个简单的子程序。
use List::Util qw(pairmap);
sub pairGroupBy(&@) {
my($irCode, @iaItems) = @_;
my %laResult = ();
pairmap {
my $lsKey = $irCode->();
if (!defined($lsKey)) {
die "Trying to pairGroup by nonexisting key '$lsKey'";
}
push @{$laResult{$lsKey}}, $a => $b;
} @iaItems;
return %laResult;
}
在子例程从定义它的同一文件中使用之前,它运行良好。当我将它移动到某个包时,变量 $a 和 $b 在 $irCode->() 回调中变得未定义。
我从List::Util source code 了解到,这段代码可以解决问题:
my $caller = caller;
local(*{$caller."::a"}) = \my $a;
local(*{$caller."::b"}) = \my $b;
所以我以这种方式修改了我的子程序:
use List::Util qw(pairmap);
sub pairGroupBy(&@) {
my($irCode, @iaItems) = @_;
my $caller = caller;
my %laResult = ();
pairmap {
no strict 'refs';
local(*{$caller."::a"}) = \$a; # <---- the line 96
local(*{$caller."::b"}) = \$b;
my $lsKey = $irCode->();
if (!defined($lsKey)) {
die "Trying to pairGroup by nonexisting key '$lsKey'";
}
push @{$laResult{$lsKey}}, $a => $b;
} @iaItems;
return %laResult;
}
但我需要使用no strict 'refs'; 行(List::Util source code 不使用它)。否则会出现错误提示:
Can't use string ("main::a") as a symbol ref while "strict refs" in use at /home/.../bin/SatFunc.pm line 96.
我的问题是:有没有更好的方法来在调用者的上下文中定义$a 和$b 变量而不使用no strict 'refs';?
我希望我的函数以与pairmap、pairgrep 等相同的方式使用。
编辑: @simbabque 询问了一个示例,如何使用该函数。所以这是一个例子:
my %laHoH = (
aa => {
color => 'yellow',
item => 'sun',
active => 1
},
bb => {
color => 'blue',
item => 'sky',
active => 1
},
cc => {
color => 'green',
item => 'grass',
active => 0
},
dd => {
color => 'blue',
item => 'watter',
active => 1
}
);
my %laGrouped = pairGroupBy {
$b->{color}
} pairgrep {
$b->{active}
} %laHoH;
函数然后返回这个结构:
{
'yellow' => [
'aa',
{
'color' => 'yellow',
'item' => 'sun',
'active' => 1
}
],
'blue' => [
'dd',
{
'active' => 1,
'item' => 'watter',
'color' => 'blue'
},
'bb',
{
'color' => 'blue',
'item' => 'sky',
'active' => 1
}
]
};
【问题讨论】:
-
请edit您的问题并包括对您的
pairGroupBy函数的示例调用。 -
不,如果你想要这种行为,真的没有更好的方法。如果 XS 未加载,则该包具有该代码
eval-ed 并且声明了全局$a、$b(使用use vars,“已被our取代") -
你应该只做
no strict 'refs';(在尽可能小的范围内)。 List::Util 不需要这样做,因为它根本没有使用 strict,但你不想跟着它做 that。
标签: perl