2017-01-05 51 views

Odpowiedz

10

Twój kod jest poprawny w ogóle, ale trzeba wyłączyć strict 'refs' aby Perl pozwala używać zmiennej treści, co odn kodowych.

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(); 
} 

Wyjście tutaj jest:

Calling foo 
fooCalling bar 
bar 

Dodałem także nawias () po wywołaniu. W ten sposób nie przekazujemy żadnych argumentów do %$sub. Jeśli tego nie zrobimy, zostanie użyta lista argumentów bieżącego podprogramu @_.


Jednak prawdopodobnie nie należy tego robić. Zwłaszcza jeśli @arr zawiera dane wejściowe użytkownika, jest to duży problem. Twój użytkownik może wstrzyknąć kod. Rozważ to:

my @arr = qw/CORE::die/; 

Teraz otrzymujemy następujący wynik:

Calling CORE::die 
Died at /home/code/scratch.pl line 1492. 

Ups. Nie chcesz tego robić. Przykład die nie jest zły, ale w ten sposób można łatwo wywołać kod w innym pakiecie, który nie był przeznaczony.

Prawdopodobnie lepiej jest wykonać dispatch table. Istnieje cały rozdział na temat tych w Wyższego rzędu Perl Marka Jason Dominus, który można download for free on his website.

Oznacza to po prostu, że umieścisz wszystkie subwoofery w haszu jako odwołania do kodu, a następnie wywołaj te w pętli. W ten sposób możesz kontrolować, które z nich są dozwolone.

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}->(); 
} 

This wyjścia:

foobarbaz 
wrong_entry is not allowed at /home/code/scratch.pl line 1494. 
+1

Dałem mężczyźnie rybę, nauczyłeś go łowić ryby. +1 – Zaid

+1

@ Zaid oh, są jeszcze dwie odpowiedzi. Jeszcze ich nie widziałem.Byłem po prostu zajęty robieniem na pół blogu tutaj jeszcze raz ...: D – simbabque

+0

HI simbabque. Dzięki. Nie wiedziałem o tym. W moim przypadku użytkownicy nie podają nazwy podprocedury w argumentach, ale dobre informacje. – Raj

7

Chcesz to zrobić za pomocą kodu odwołuje.

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

gdzie @arr zawiera skalary takie jak

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

lub

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

można manipulować te skalary, jak każdy inny, tworząc swoją tablicę. Jednak bardziej powszechne i użyteczne jest użycie ich jako wartości w haśle, tworząc tabelę wysyłkową .

Aby uzyskać referencje do kodu, patrz perlref, a także pomocna może być this post.