I have a function for case insensitive sorting. It works if it's from the same package, but not otherwise.
This works:
my @arr = sort {lc $a cmp lc $b} @list;
This works (if a function called "isort" is defined in the same file):
my @arr = sort isort @list;
This does not (function exported with Exporter from another package):
my @arr = sort isort @list;
This does not (function referred to explicitly by package name):
my @arr = sort Utils::isort @list;
What is going on? How do I put a sorting function in another package?
What evidence do you have for it not working? Have you put a print()
statement in the subroutine to see if it's being called?
I suspect you're being tripped up by this (from perldoc -f sort
):
$a
and$b
are set as package globals in the package the sort() is called from. That means$main::a
and$main::b
(or$::a
and$::b
) in themain
package,$FooPack::a
and$FooPack::b
in theFooPack
package, etc.
Oh, and later on it's more specific:
Sort subroutines written using
$a
and$b
are bound to their calling package. It is possible, but of limited interest, to define them in a different package, since the subroutine must still refer to the calling package's$a
and$b
:package Foo; sub lexi { $Bar::a cmp $Bar::b } package Bar; ... sort Foo::lexi ...
Use the prototyped versions (see above) for a more generic alternative.
The "prototyped versions" are described above like this:
If the subroutine's prototype is
($$)
, the elements to be compared are passed by reference in@_
, as for a normal subroutine. This is slower than unprototyped subroutines, where the elements to be compared are passed into the subroutine as the package global variables$a
and$b
(see example below).
So you could try rewriting your subroutine like this:
package Utils;
sub isort ($$) {
my ($a, $b) = @_;
# existing code...
}
And then calling it using one of your last two alternatives.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With