Home > Software engineering >  Perl dynamic function reference
Perl dynamic function reference

Time:05-08

Given a package name $package and a function name from within that package $function, I can create a reference to that function:

my $ref = eval( "\\&${package}::${function}" );

As a complete example:

#!/usr/bin/perl -w

use strict;

package foo;

sub func()
{
    print "foo::func\n";
}

package main;

my $package = "foo";
my $function = "func";

my $ref = eval( "\\&${package}::$function" );
$ref->();

I do not particularly like that eval() in there and wonder if the same result could be achieved without eval()?

CodePudding user response:

This can be made by accessing the function via the symbol table. Note that this needs no strict 'refs', which can be restricted to a block though:

my $package = "foo";
my $function = "func";
my $ref = do {
   no strict 'refs';
   *{"${package}::${function}"};
};
$ref->();

Example:

getref("Foo","bar")->(); # Foo::bar
getref("Bar","foo")->(); # Bar::foo

sub getref {
    my ($pkg,$sub) = @_;
    no strict 'refs';
    return *{"${pkg}::${sub}"};
}


package Foo;
sub bar { print "Foo::bar\n" }

package Bar;
sub foo { print "Bar::foo\n" }

CodePudding user response:

Using strings to refer to subroutines is seldom the right way. If you are doing it this way, you are most likely doing something wrong. You can use a code reference to store a reference to a function, in a scalar or hash. The hash allows you to correctly look up code references via string inputs.

use strict;
use warnings;

package foo;
sub func() {
    print "inside foo::func (@_)\n";
}

package main;

# use a direct reference, in a scalar variable
my $ref = \&foo::func;
$ref->(1,2,3);

# ...or in a hash
my $pack = "foo";
my $func = "func";
my %table = ( foo => { func => \&foo::func } );
$table{$pack}{$func}->(qw(a b c));

Output:

inside foo::func (1 2 3)
inside foo::func (a b c)
  • Related