8

我有一个脚本和一个包,如下所示:

# file: sortscript.pl
use strict;
use warnings;
use SortPackage;

my @arrays = ([1,"array1"],[10,"array3"],[4,"array2"]);

print "Using sort outside package\n";
foreach (sort SortPackage::simplesort @arrays){
    print $_->[1],"\n";
}

print "\nUsing sort in same package\n";
SortPackage::sort_from_same_package(@arrays);

--

# file: SortPackage.pm
use strict;
use warnings;
package SortPackage;

sub simplesort{
    return ($a->[0] <=> $b->[0]);
}

sub sort_from_same_package{
    my @arrs = @_;
    foreach (sort simplesort @arrs){
        print $_->[1],"\n";
    } 
}
1;

运行脚本会产生输出:

$ perl sortscript.pl
Using sort outside package
Use of uninitialized value in numeric comparison (<=>) at SortPackage.pm line 15.
Use of uninitialized value in numeric comparison (<=>) at SortPackage.pm line 15.
Use of uninitialized value in numeric comparison (<=>) at SortPackage.pm line 15.
Use of uninitialized value in numeric comparison (<=>) at SortPackage.pm line 15.
Use of uninitialized value in numeric comparison (<=>) at SortPackage.pm line 15.
Use of uninitialized value in numeric comparison (<=>) at SortPackage.pm line 15.
array1
array3
array2

Using sort in same package
array1
array2
array3

为什么当它在另一个包中时,我无法正确使用子例程进行排序?

4

3 回答 3

6

$a并且$b是特殊的“包全局”变量。

要使用主范围$a$b比较器功能,必须引用$::aor $main::a(同样适用于$b)。

但是,当从任何其他包甚至从其自己的包中调用时,该比较器函数将不起作用。

请参阅perlvars帮助和perldoc功能sort。解决方案也在后面的帮助文本中:

如果子例程的原型是"($$)",则要比较的元素通过引用传递 in @_,就像普通子例程一样。这比非原型子例程要慢,其中要比较的元素作为包全局变量传递到子例程中$a$b参见下面的示例)。$a请注意,在后一种情况下,将和声明$b为词法通常会适得其反。

于 2012-07-16T16:22:42.080 回答
6

如前所述,$a并且$b是包全局变量,因此另一种解决方案是将调用站点的全局变量临时别名为 package 中的全局变量SortPackage

{
    local (*a, *b) = (*SortPackage::a, *SortPackage::b);
    foreach (sort SortPackage::simplesort @arrays){
        print $_->[1],"\n";
    }
}

但这当然很丑陋。我只需要SortPackage导出一个完整的排序例程,而不仅仅是一个比较器:

package SortPackage;
use strict;

sub _sort_by_first_element_comparator {
    return $a->[0] <=> $b->[0];
}

sub sort_by_first_element {
    return sort _sort_by_first_element_comparator @_;
}
于 2012-07-16T17:47:20.197 回答
5

特殊变量$a$b是包全局变量。您的子例程需要$SortPackage::a$SortPackage::b. 当您从 调用它时sortscript.pl,变量$main::a$main::b由 设置sort

解决方案是使用原型子程序:

package SortPackage;

sub simplesort ($$) {
    return ($_[0]->[0] <=> $_[1]->[0]);
}

它有点慢(因为您传递了实际参数,而不是读取预设的全局变量),但它允许您在尝试时按名称使用其他包中的子例程。

于 2012-07-16T16:26:29.193 回答