2016-03-03 15 views
6

pracuję nad aktualizacją niektóre bardzo starego kodu Perl (nie mój kod) i natknąłem się na następujący w podprogramie:Co robi gwiazdka Sigil Perl zrobić

sub DoEvent { 
    local(*eventWEH, $foreachFunc, @args) = @_; 
    $ret = do $foreachFunc(*eventWEH, @args); 
} 

To wydawało się działać prawidłowo w Perl 5.6 0,1, ale już nie pracuje w Perl 5.22, co daje błąd składni po prostu zrób $ foreachFun (

Co jest celem gwiazdką przed zmiennej * eventWEH?

Gdyby to było „C” Sugerowałbym jakiś wskaźnik. Jakieś sugestie?

ETA: Ten sub zostaje wywołany z wieloma różnymi typami dla pierwszego parametru. Na przykład:

&DoEvent($abc, "DoAbc", @args); 

i

&DoEvent(@xyz, "DoXyz", @args); 

Tak jak za podane odpowiedzi, wygląda na to, * eventWEH może przybrać inny typ danych, aby dopasować cokolwiek parametr jest przekazywany do sub.

+0

Czy jesteś pewien, że to nie są '& DoEvent (\ $ abc," DoXyz ", @args)' i '& DoEvent (\ @ xyz," DoXyz ", @args)'? To, co napisałeś, nie ma większego sensu. – ikegami

Odpowiedz

2

Jest to sigil symbolu nazw, który zawiera wszystkie pozostałe typy. W starszym kodzie Perla jest zwykle używany do obsługi uchwytów plików. Współczesny Perl powinien używać prostych skalarów - tj. $.

2

Jest to glob, który bezpośrednio przechodzi do tabeli symboli. W ten sposób możesz uzyskać dostęp do zmiennej bez odwoływania się do typu (lub dowolnego typu o tej nazwie). Zdarza się, że rzadko używasz go w Perlu w dzisiejszych czasach.

Oto niektóre referencje: on symbol table, an interesting use of it i nieco z overview. Książki "Programowanie Perla" i "Mastering Perl" mają zasięg autorski.

13

Błąd składniowy nie ma nic wspólnego z globs (symbole z symbolem gwiazdki). Błąd składni wynika z usunięcia do $func(LIST) w wersji 5.20. Wymienić

$ret = do $foreachFunc(*eventWEH, @args); 

z

$ret = $foreachFunc->(*eventWEH, @args); 

Co do twojego pytania dosłownym, *foo jest typeglob lub glob za krótki. Glob jest pełnomocnik instancji następującym C strukturze:

struct gp { 
    SV *  gp_sv;   /* scalar value */ 
    struct io * gp_io;   /* filehandle value */ 
    CV *  gp_cv;   /* subroutine value */ 
    U32   gp_cvgen;  /* generational validity of cached gp_cv */ 
    U32   gp_refcnt;  /* how many globs point to this? */ 
    HV *  gp_hv;   /* hash value */ 
    AV *  gp_av;   /* array value */ 
    CV *  gp_form;  /* format value */ 
    GV *  gp_egv;   /* effective gv, if *glob */ 
    PERL_BITFIELD32 gp_line:31; /* line first declared at (for -w) */ 
    PERL_BITFIELD32 gp_flags:1; 
    HEK *  gp_file_hek; /* file first declared in (for -w) */ 
}; 

Globs są wykorzystywane przede wszystkim wewnętrznie, choć niektóre uchwyty plików są dostępne głównie za pośrednictwem nazwanych globs (*STDIN, *STDOUT i *STDERR), i są one wykorzystywane do tworzyć aliasy (*foo = \&bar;).

+1

'perl -i ~ -pe's/do (\ $? \ W +) (? = \()/$ 1 ->/g '* .pl' lub coś podobnego powinno je wszystkie naprawić – ikegami

0

W dawnych czasach, trzeba by użyć typeglob przejść wokół uchwytu pliku, tak jak tutaj:

# eventWEH is a global filehandle 
open(eventWEH, $filename) or die "Couldn't open $filename: $!"; 
somefunc(*eventWEH); 

Ale dziś masz odpowiednich uchwytów plików leksykalne, więc można zrobić

my $event_fh; 
open($event_fh, '<', $filename) or die "Couldn't open $filename: $!"; 
somefunc($event_fh); 
+0

W obecnych czasach nadal używaj typeglobów do przechodzenia wokół uchwytów plików, po prostu przechowujemy referencje do nich w skalarach. 'print (" $ event_fh \ n ");'. – ikegami

+0

Nie musimy tego jednak robić. Możemy umieścić uchwyt pliku bezpośrednio w skalarnie 'perl -e'my $ fh = \ * STDOUT; print ($ fh" $ fh \ n "); $ fh = * $ fh {IO}; print ($ fh" $ fh \ n ");' ' – ikegami