Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I call a subroutine at a hard-coded address in Perl?

Tags:

perl

eval

Let's say I have the following piece of code:

my $compiled = eval 'sub { print( "Hello World\n" ); }';

I can call this by writing:

$compiled->();

So far so good. Now imagine I create 10 functions:

my @fns = ();
for ( my $i = 0; $i < 10; $i++ ) {
  push( @fns, eval "sub { print( 'I am function $i\n' ); }" );
}

I can call these 10 functions as follows:

foreach ( @fns ) {
  $_->();
}

Now, I want to create a dynamic function that calls each of my 10 functions explicitly:

my $evalcode = "sub {";
foreach ( @fns ) {
    # if I print $_ it shows something like
    #   "CODE(0x94084f8)", but trying to
    #   call "CODE(0x94084f8)->()" is invalid
    $evalcode .= "$_->();";
}
$evalcode .= "}";


my $dynamic_fn = eval $evalcode;
$dynamic_fn->();

Is it possible to take a stringified reference to a subroutine and call this directly?

PS why, you ask? Because I would like to write a dynamic routine that constructs a chain of if ( m/.../ ) { } elsif ( m/.../ ) { } ... checks that then call dynamic functions depending on the input string.

like image 233
PP. Avatar asked Nov 28 '22 03:11

PP.


2 Answers

Instead of string evals, you might want to use regular lexical closures:

my @functions;

for my $i (0 .. 9) {
    push @functions, sub { print "I am function $i\n" };
}

my $call_all_funcs = sub {
    for my $func (@functions) {
        $func->();
    }
};

$call_all_funcs->();

It is also possible to retrieve a code reference based in its address, but that'd be much more elaborate, harder to understand, and generally not a very good idea.

like image 79
rafl Avatar answered Dec 05 '22 15:12

rafl


How about using a closure instead of an eval string?

sub combine_subrefs {
  my @subs = @_;
  return sub { foreach my $subref (@subs) { $subref->() } };
}

my $dynamic_fn = combine_subrefs( @fns );
$dynamic_fn->();

I'm sure you can adapt this to do the elsif thing you mentioned as well.

like image 40
aschepler Avatar answered Dec 05 '22 15:12

aschepler