In general, your code is correct, but you need to disable strict 'refs' so that Perl allows you to use the contents of the variable as ref code.
use strict; use warnings; sub foo { print "foo" } sub bar { print "bar" } my @arr = qw/foo bar/; foreach my $sub (@arr) { no strict 'refs'; print "Calling $sub\n"; &$sub(); }
The output is here:
Calling foo fooCalling bar bar
I also added a parenthesis () after the call. Therefore, we do not pass the arguments to %$sub . If we do not, the argument list @_ current routine will be used.
However, you probably shouldn't do this. Especially if @arr contains user input, this is a big problem. Your user can enter the code. Consider this:
my @arr = qw/CORE::die/;
Now we get the following result:
Calling CORE::die Died at /home/code/scratch.pl line 1492.
Unfortunately. You do not want to do this. The die example is not very bad, but you can easily call the code in another package that was not intended.
It is probably best to do a distribution table. There is a whole chapter about those in Perl of a higher order, Mark Jason Dominus, which you can download for free on your website .
This basically means that you put all the sub-sites in the hash as links to the code, and then call them in your loop. This way you can control which ones are allowed.
use strict; use warnings; sub baz { print "baz" } my %dispatch = ( foo => sub { print "foo" }, bar => sub { print "bar" }, baz => \&baz, ); my @arr = qw/foo bar baz wrong_entry/; foreach my $sub ( @arr ) { die "$sub is not allowed" unless exists $dispatch{$sub}; $dispatch{$sub}->(); }
It is output:
foobarbaz wrong_entry is not allowed at /home/code/scratch.pl line 1494.