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

Mat*_*eck 8 sorting perl 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);
Run Code Online (Sandbox Code Playgroud)

-

# 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;
Run Code Online (Sandbox Code Playgroud)

运行脚本会生成输出:

$ 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
Run Code Online (Sandbox Code Playgroud)

为什么我无法正确使用子程序进行排序?

Aln*_*tak 6

$a并且$b是特殊的"包全局"变量.

要使用主示波器$a$b比较器功能必须参考$::a$main::a(同样适用于$b).

然而,当从任何其他包调用时,或者甚至在其自己的包内调用时,该比较器函数不起作用.

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

如果子例程的原型是"($$)",那么要比较的元素将通过引用传递@_,就像普通子例程一样.这比unprototyped子程序,其中待比较的元件被传入子程序作为包全局变量慢$a$b(见下例).请注意,在后一种情况下,声明$a$b作为词汇通常会适得其反.


Sea*_*ean 6

正如已经提到的那样,$a并且$b是包全局变量,所以另一种解决方案是将调用站点的全局变量临时别名化为包中的全局变量SortPackage:

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

但当然,这非常难看.我只是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 @_;
}
Run Code Online (Sandbox Code Playgroud)


che*_*ner 5

特殊变量$a$b包全局变量.您的子程序期望$SortPackage::a$SortPackage::b.当你从中调用它时sortscript.pl,变量$main::a$main::b正在设置sort.

解决方案是使用prototyped子例程:

package SortPackage;

sub simplesort ($$) {
    return ($_[0]->[0] <=> $_[1]->[0]);
}
Run Code Online (Sandbox Code Playgroud)

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