2017-01-05 12 views

ответ

10

Ваш код правильный в целом, но вам нужно отключить 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. 
+1

Я дал человеку рыбу, вы научили его, как ловить рыбу. +1 – Zaid

+1

@ Zaid oh, есть еще два ответа. Я их еще не видел.Я был просто занят взломать половину сообщения в блоге здесь снова ...: D – simbabque

+0

HI simbabque. Благодарю. Я этого не знал. В моем случае пользователи не предоставляют имя подпрограммы в аргументах, но имеют хорошую информацию. – Raj

7

Вы хотите сделать, используя код ссылки.

foreach my $sub (@arr) 
{ 
    $sub->(); 
} 

@arr где содержит скаляры, такие как

my $rc = sub { print "Anonymous subroutine\n" }; 

или

sub func { print "Named sub\n" } 
my $rc = \&func; 

Вы можете управлять этими скаляры, как вы бы любой другой, чтобы сформировать свой массив. Тем не менее, более распространено и полезно использовать их в качестве значений в хеше, создавая таблицу рассылки .

См. perlref для создания ссылок на код, а также this post.