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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With