Home > database >  How to stack function definitions in perl (call them all at once)?
How to stack function definitions in perl (call them all at once)?

Time:10-20

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 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

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');
}
  • Related