Perl 排序不会使用另一个包中的函数

fel*_*the 6 perl

我有一个不区分大小写的排序功能。如果它来自同一个包,它就可以工作,否则就不行。

这有效:

my @arr = sort {lc $a cmp lc $b} @list;
Run Code Online (Sandbox Code Playgroud)

这有效(如果在同一个文件中定义了一个名为“isort”的函数):

my @arr = sort isort @list;
Run Code Online (Sandbox Code Playgroud)

这不会(从另一个包中使用 Exporter 导出的函数):

my @arr = sort isort @list;
Run Code Online (Sandbox Code Playgroud)

这不会(由包名显式引用的函数):

my @arr = sort Utils::isort @list;
Run Code Online (Sandbox Code Playgroud)

到底是怎么回事?如何将排序功能放在另一个包中?

Dav*_*oss 5

你有什么证据证明它不起作用?你有没有print()在子程序中放置一个语句来查看它是否被调用?

我怀疑你被这个(来自perldoc -f sort)绊倒了:

$a$b在调用 sort() 的包中设置为包全局变量。这意味着$main::a$main::b(或$::a$::b)在main包,$FooPack::a$FooPack::b在该FooPack包等

哦,后来它更具体:

使用$a$b绑定到它们的调用包的排序子例程。在不同的包中定义它们是可能的,但兴趣有限,因为子例程仍然必须引用调用包的$aand $b

package Foo;
sub lexi { $Bar::a cmp $Bar::b }
package Bar;
... sort Foo::lexi ...
Run Code Online (Sandbox Code Playgroud)

使用原型版本(见上文)以获得更通用的替代方案。

“原型版本”在上面是这样描述的:

如果子程序的原型是($$),则要比较的元素通过引用传递给@_,就像普通子程序一样。这比非原型子例程慢,其中要比较的元素作为包全局变量$a$b(参见下面的示例)传递到子例程中。

所以你可以尝试像这样重写你的子程序:

package Utils;

sub isort ($$) {
  my ($a, $b) = @_;

  # existing code...
}
Run Code Online (Sandbox Code Playgroud)

然后使用最后两个选择之一调用它。