So I want something like:
module0.pl
sub fun {
print "fun $_[0] from 0\n"
}
1
module1.pl
sub fun {
print "fun $_[0] from 1\n"
}
1
main.pl
BEGIN{push @INC, "."};
require "module0.pl";
require "module1.pl";
fun("test")
Which will print (in any order - I don't care) :
fun test from 0
fun test from 1
Is it possible - and what is the most elegant syntax to do it?
So you want to call a list of subs from various packages (here equally named) ?
One way, using normal packages
package Pack1;
use warnings;
use strict;
use feature 'say';
sub fun { say "fun $_[0] from ", __PACKAGE__ }
1;
The calling program, in the same directory with this package (and its counterpart Pack2
)
use warnings;
use strict;
use feature 'say';
use FindBin qw($RealBin);
use lib $RealBin;
use Pack1;
use Pack2;
for my $packname (qw(Pack1 Pack2)) {
MAKENAME: {
no strict 'refs';
my $fun_name = $packname . '::' . 'fun';
$fun_name->("hi") if exists &{$fun_name};
}
}
I put that scoped no strict 'refs'
in another block, and name the block, just so; if this is all that is done in the loop there is no need to introduce another scope.† We need the refs
stricture off for using it as a subroutine reference but then it makes sense to scope the name itself as well.
A few notes
I don't know why those are .pl
files which are require
-ed; they should be packages and I wrote them that way. Let me know if there is actually a specific (and unbeatable) reason for them to be require
-ed programs
Add directories to @INC
using the lib pragma with $FindBin::RealBin, not by hacking @INC
† Or copy the coderef
for my $packname (qw(Pack1 Pack2)) {
my $fun = \&{ $packname . '::' . 'fun' };
$fun->('hi');
}
But if we do need to check for existence that should rather be
for my $packname (qw(Pack1 Pack2)) {
my $fun_name = $packname . '::' . 'fun';
next if not exists &{$fun_name};
my $fun = \&{$fun_name};
$fun->('hi');
}