2017-02-15 49 views
12

Dzisiaj natknąłem się na coś w Perlu, którego nie znałem: "lokalizuje" zmienną, do której przypisane są elementy z listy iterowanej.Dlaczego foreach Perla nie wymaga deklarowania swojej zmiennej za pomocą mojego?

To oczywiście jest udokumentowane w dokumentacji Perla - jednak nie udało mi się go zapamiętać ani przeczytać.

Poniższy skrypt pokazuje, co to znaczy:

use warnings; 
use strict; 

my $g = 99; 

foreach $g (1..5) { 
    p($g); 
} 

sub p { 
    my $l = shift; 
    printf ("%2d %2d\n", $g, $l); 
} 

drukuje skrypt

99 1 
99 2 
99 3 
99 4 
99 5 

ponieważ $g jest "miejscowe" do pętli foreach.

O ile mogę powiedzieć, nie ma żadnej różnicy, gdybym dodał my do $g w pętli foreach:

foreach my $g (1..5) { 

Faktycznie, skończyło się to robi, bo czuję, że czyni go bardziej zrozumiałym, że zmienna jest lokalny w pętli.

Moje pytanie brzmi teraz: czy istnieje scenariusz, w którym moje użycie my ma znaczenie (biorąc pod uwagę, że $g jest już zadeklarowane globalnie).

+2

Foreach nie wymaga mojej deklaracji, jeśli została zgłoszona na całym świecie. Dziwne jest jednak, że nie będzie narzekać, że deklarujesz to ponownie. Na przykład, jeśli usuniesz zasięg, zarzuci on, że już zadeklarowałeś '$ g', że pójdę i trochę to zbadam. –

+0

Jeśli zmienna została wcześniej zadeklarowana za pomocą my, używa tej zmiennej zamiast globalnej, ale nadal jest zlokalizowana w pętli. Ta * niejawna lokalizacja występuje tylko w pętli foreach *. http://perldoc.perl.org/perlsyn.html#Foreach-Loops – user3606329

+0

@ user3606329 To prawda, ale jeśli weźmiesz ten kod i usuniesz zakres, spowoduje to błąd. Zmienna nie jest jeszcze w pętli, jest częścią instrukcji foreach. –

Odpowiedz

8

Badany zachowanie udokumentowane Foreach Loops in perlsyn

W foreach pętla iteruje normalną wartość listy i określa zmienną skalarną VAR być każdy element listy kolei. Jeśli zmienna jest poprzedzona słowem kluczowym my, jest ona określana leksykalnie i dlatego jest widoczna tylko w pętli.

który kontynuuje wyjaśnienia

W przeciwnym wypadku, zmienna jest niejawnie lokalna w pętli i odzyskuje swoją dawną wartość po wyjściu z pętli. Jeśli zmienna została wcześniej zadeklarowana przy użyciu my, używa ona tej zmiennej zamiast globalnej, ale nadal jest zlokalizowana w pętli.

Zatem nie powinno być żadnej różnicy pomiędzy lokalizowaniu go my lub pozostawiając że do foreach.

Nieco ciekawość jest

Pośrednia lokalizacja pojawia tylko w foreach pętli.

Wszystko to dodatkowo wyjaśnione w tym fragmencie od Private Variables via my() from perlsub

W foreach pętli domyślnie określenie zakresu jego indeks zmiennej dynamicznie w sposób local.Jeśli jednak zmienna indeksowa ma prefiks ze słowem kluczowym my lub jeśli istnieje już leksykalny o tej nazwie w zakresie, to tworzony jest nowy leksykalny.

Od nowego leksykalnym jest utworzony wewnątrz w obu przypadkach nie może być dowolny praktyczna różnica.

Całkowicie popieram i polecam umieszczenie tam my.

+0

To jest zrozumiałe. Jednak problem, który tutaj widzę, polega na tym, że '$ g' nie jest jeszcze w pętli. więc jeśli '$ g' nie jest zadeklarowany i przypisano mu wartość wcześniejszą, to' $ g' jest w rzeczywistości pustą wartością. –

+0

@Gerry In 'foreach my $ i (1..4) {}' zakres '$ i' jest ograniczony do pętli. Nie istnieje "_przedtem". To samo jest bez 'my', jeśli' $ i' zostało zadeklarowane wcześniej - jest zlokalizowane w zasięgu pętli, gdy tylko zostanie zauważone. O tym właśnie informują powyższe cytaty. – zdim

+0

ok, dziękuję zdim. To ma sens. –