在这个Perl子程序中“使用vars”有什么意义?

时间:2010-02-14 16:49:52

标签: perl

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)行的重点是什么。即使我评论它,我得到相同的输出&警告。

3 个答案:

答案 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::UtilList::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中,我正在使用调用包中的包版本。这就是为什么格雷厄姆让他们成为彼此的别名。