在Mastering Perl的其中一章中,brian d foy展示了List::Util的这个片段:
sub reduce(&@) {
my $code = shift;
no strict "refs";
return shift unless @_ > 1;
use vars qw($a $b);
my $caller = caller;
local(*{$caller . "::a"}) = \my $a;
local(*{$caller . "::b"}) = \my $b;
$a = shift;
foreach(@_) {
$b = $_;
$a = &{$code}();
}
$a;
}
我不明白use vars qw($a $b)
行的重点是什么。即使我评论它,我得到相同的输出&警告。
答案 0 :(得分:11)
这样做是因为List :: Util在内部使用了reduce()函数。
在use vars
的绝对值中,使用该函数时会发出以下警告:
Name "List::MyUtil::a" used only once: possible typo at a.pl line 35.
Name "List::MyUtil::b" used only once: possible typo at a.pl line 35.
您可以通过运行以下代码自行查看:
use strict;
use warnings;
package List::MyUtil;
sub reduce (&@) {
# INSERT THE TEXT FROM SUBROUTINE HERE - deleted to save space in the answer
}
sub x {
return reduce(sub {$a+$b}, 1,2,3);
}
package main;
my $res = List::MyUtil::x();
print "$res\n";
然后在use vars
禁用的情况下再次运行它。
答案 1 :(得分:2)
正如DVK所说,如果我们运行带有use vars
注释掉的代码,我们将收到有关仅使用一次变量的警告。
另一种抑制警告的方法是在呼叫方 - 即调用reduce
而不是reduce
函数内。当使用List::Util
或List::MoreUtils
中带有代码引用的函数(例如,pairwise
)时,必须执行此操作。这两种方法都适用于呼叫方:
my @sums = pairwise { no warnings 'once'; $a + $b } @x, @y;
my @sums = pairwise { our($a, $b); $a + $b } @x, @y;
答案 2 :(得分:0)
在该代码解释之后的段落中。在同一范围内有包和词汇变量的混合:
reduce的其余部分通过将两个元素放入包变量$ a和$ b来实现排序。 Graham用这些名称定义词法变量,并通过使用符号引用立即为调用包中的$ a和$ b分配typeglobs。之后,$ a和$ b的值是词法版本。当他调用子例程参数& {$ code}()时,该代码会查看其包变量,这些是我编写子例程时生效的变量。了解?在reduce中,我使用的是lexical版本,但在$ code中,我正在使用调用包中的包版本。这就是为什么格雷厄姆让他们成为彼此的别名。