使用另一个包中的排序子例程

时间:2012-07-16 16:15:10

标签: perl sorting package subroutine

我有一个脚本和包这样:

# 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

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

3 个答案:

答案 0 :(得分:6)

如前所述,$a$b是包全局变量,因此另一种解决方案是将调用站点的全局变量临时别名为包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 @_;
}

答案 1 :(得分:5)

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

要使用主范围的$a$b,您的比较器功能必须引用$::a$main::a(同样适用于$b)。< / p>

然而,当从任何其他包中调用时, 时,将不会工作。或者甚至在其自己的包中。

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

  

如果子例程的原型是"($$)",那么元素就是                  比较在@_中通过引用传递,与法线相同                  子程序。这比非原型子程序慢,                  将要比较的元素传递给                  子程序作为包全局变量$a$b(参见                  例子如下)。请注意,在后一种情况下,通常是这样                  将$a$b声明为词汇,会产生反作用。

答案 2 :(得分:5)

特殊变量$a$b是包全局变量。您的子例程需要$SortPackage::a$SortPackage::b。当您从sortscript.pl拨打电话时,变量$main::a$main::bsort设置。

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

package SortPackage;

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

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