Maybe yet another layer of abstraction might make it even nicer:
package Array::Extract;
my $worker_pkg;
my $priority = -1;
sub import {
my ($class, %args) = @_;
if (exists $args{priority}) {
# Register new implementation
if ($args{priority} > $priority) {
$worker_pkg = caller;
$priority = $args{priority};
}
} else {
warn "Using $worker_pkg, priority $priority\n";
$class->SUPER::import(ARRAY => $worker_pkg);
}
}
# Worker.pm
package Array::Extract::Worker;
use Array::Extract priority => 1;
# somewhere else
use Array::Extract::Worker; # has to be used first
use Array::Extract;
This avoids these global variables that have been described as "action at a distance". Using "priority", you can even have several implementations, and it will choose the one with the highest priority; but that's just an extra bonus, it'll work without priorities too.