Ваш код правильный в целом, но вам нужно отключить strict 'refs'
сделать Perl позволяет использовать переменную содержимое в виде кода рефов.
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();
}
Выход здесь:
Calling foo
fooCalling bar
bar
Я также добавил скобка ()
после вызова. Таким образом мы не передаем аргументы %$sub
. Если мы этого не сделаем, будет использован список аргументов @_
текущей подпрограммы.
Однако, вероятно, вы не должны этого делать. Особенно, если @arr
содержит пользовательский ввод, это большая проблема. Ваш пользователь может ввести код. Рассмотрим это:
my @arr = qw/CORE::die/;
Теперь мы получаем следующий вывод:
Calling CORE::die
Died at /home/code/scratch.pl line 1492.
К сожалению. Вы не хотите этого делать. Пример die
не очень плохой, но вот вы можете легко вызвать код в другом пакете, который не был предназначен.
Возможно, лучше сделать dispatch table. Существует целая глава о том, что в Более высокий заказ Perl от Марка Джейсона Домина, который вы можете download for free on his website.
В основном это означает, что вы помещаете все субтитры в хэш как ссылки на код, а затем вызываете их в своем цикле. Таким образом, вы можете контролировать, какие из них разрешены.
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}->();
}
Это выходы:
foobarbaz
wrong_entry is not allowed at /home/code/scratch.pl line 1494.
'(\ & $ name) -> (@ args)' – ikegami