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?
CodePudding user response:
So you want to call equally named subs from various packages? (Sounds like trouble, no? :)
One way, using normal packages
package Pack1;
# Last modified: 2022 Oct 19 (10:52)
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.†
A few notes
I don't know why those are
.pl
files which arerequire
-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 berequire
-ed programsAdd directories to
@INC
using the lib pragma with $FindBin::RealBin, not by hacking@INC
Let me mention it again: hopefully this isn't meant to be a production-code device.
† Or
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');
}