首页 > 解决方案 > Perl 排序不会使用另一个包中的函数

问题描述

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

这有效:

my @arr = sort {lc $a cmp lc $b} @list;

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

my @arr = sort isort @list;

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

my @arr = sort isort @list;

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

my @arr = sort Utils::isort @list;

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

标签: perl

解决方案


你有什么证据证明它不起作用?您是否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 ...

使用原型版本(见上文)作为更通用的替代方案。

上面对“原型版本”的描述如下:

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

因此,您可以尝试像这样重写您的子例程:

package Utils;

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

  # existing code...
}

然后使用最后两个替代方案之一调用它。


推荐阅读